Kolejność rekordów w bazie danych.

0

WSTĘP:
Napisałem apkę - generator wniosków w .NET, która łączy się z bazą danych w celu pobrania pól do wniosku. W bazie danych są dwie tabele - jedna "słownikowa", w której przechowywane są wszystkie pola wraz ze specyfikacją (maksymalną długością pola, maksymalną ilością występowania, nazwą, numerem), druga to tabela "robocza", która pobiera z tabeli słownikowej pożądane dane, a jej zawartość zależy od tego co użytkownik wybiera poprzez interfejs graficzny.
PROBLEM:
Pola we wniosku są w kolejności rosnącej po numerze pola. Korzystam tutaj z komendy SQL: "SELECT * FROM tabela ORDER BY ...". Problem w tym, że potrzebuje żeby niektóre pola powtarzały się dopiero po wystąpieniu całej grupy. Np. pola od 400 do 403 tworzą jedną grupą (opis odbiornika). Potrzebuję sprawić aby po dodaniu przez użytkownika kolejnych pól 400 i 401... efekt nie był taki: 400. 400. 401. 401. 402. 403. tylko 400. 401. 402. 403. 400. 401.
Ktoś ma jakąś propozycję rozwiązania tego problemu?

1

Pierwszy pomysł - dodaj dodatkową kolumnę w tabeli opisującą grupę odbiorników (np 1, 2, 3 albo opis słowny) - i wtedy orderuj najpierw po tej nowej kolumnie a potem po tych liczbach

0
Pinek napisał(a):

Pierwszy pomysł - dodaj dodatkową kolumnę w tabeli opisującą grupę odbiorników (np 1, 2, 3 albo opis słowny) - i wtedy orderuj najpierw po tej nowej kolumnie a potem po tych liczbach

Problem w tym rozwiązaniu polega na tym, że te pola wtedy automatycznie przesunął się na koniec. Wyjdzie coś w stylu 005. 010. 400. 401. 700. 800. 400. 401. 400. 401. A ja potrzebuje żeby one dalej były w tym samym miejscu czyli 005. 010. 400. 401. 400. 401. 400. 401. 700. 800.

1

Nie rozumiem zatem schematu według którego chcesz rezultaty. Czego właściwie oczekujesz, jakiej kolejności? Podaj przykład z opisem.

0
Pinek napisał(a):

Nie rozumiem zatem schematu według którego chcesz rezultaty. Czego właściwie oczekujesz, jakiej kolejności? Podaj przykład z opisem.

Ogólnie wniosek ma pola od 005 do 999. Występują one w kolejności rosnącej z tym wyjątkiem, że jest grupa pól opisująca odbiornik są to pola dokładnie od 400 do 408. Problem polega, że ta grupa może występować kilkukrotnie i wtedy kolejność również jest rosnąca z tym tylko wyjątkiem, że każda kolejna tego typu grupa następuje po sobie. Czyli przykładowo jeżeli dodam dwa odbiorniki to mam oprócz pozostałych pól które będą w kolejności rosnącej np. 005. 006. 100. 300. 700. mam mieć rezultat: 005. 006. 100. 300. 400. 401. 402. 403. 404. 405. 406. 407. 408. 400. 401. 402. 403. 404. 405. 406. 407. 408. 700.

2

No to ja bym twoje zapytanie sqlowe rozbił na 3 części:

  1. pobranie rekordów z numerem od 005 do 399
  2. Pobranie rekordów z numerem od 400 do 408, z czego każdy posortowany najpierw według tej dodatkowej kolumny (grupy)
  3. Pobranie pozostałych rekordów, czyli od 409 do 999

Kolejne podzapytania łączysz poprzez UNION bądź UNION ALL.

Co do tej kolumny od grupy: każdy rekord ją niech zawiera, tylko że dla numerów od 400 do 408 coś tam będzie, a dla innych NULL czy tam puste.

0
Pinek napisał(a):

No to ja bym twoje zapytanie sqlowe rozbił na 3 części:

  1. pobranie rekordów z numerem od 005 do 399
  2. Pobranie rekordów z numerem od 400 do 408, z czego każdy posortowany najpierw według tej dodatkowej kolumny (grupy)
  3. Pobranie pozostałych rekordów, czyli od 409 do 999

Kolejne podzapytania łączysz poprzez UNION bądź UNION ALL.

Co do tej kolumny od grupy: każdy rekord ją niech zawiera, tylko że dla numerów od 400 do 408 coś tam będzie, a dla innych NULL czy tam puste.

SELECT * FROM tabela WHERE ID BETWEEN 005 AND 399
UNION
SELECT * FROM tabela WHERE ID BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR) ASC, CAST(ID AS VARCHAR) ASC
UNION
SELECT * FROM tabela WHERE ID BETWEEN 409 AND 999

Mam komunikat "Msg 156, Level 15, State 1, Line 4
Incorrect syntax near the keyword 'UNION'." Gdzie jest błąd?

1

Kurczę wiesz co, ciężko mi teraz ci podpowiadać krok po kroku - spróbuj najpierw Zunionować pierwszy select z drugim, bez dodatkowego ordera. Tak btw. to widzę że chyba Postgresa używasz?

0
Pinek napisał(a):

Kurczę wiesz co, ciężko mi teraz ci podpowiadać krok po kroku - spróbuj najpierw Zunionować pierwszy select z drugim, bez dodatkowego ordera. Tak btw. to widzę że chyba Postgresa używasz?

Microsoft SQL Server Management Studio :D Dobra jakoś pokombinuje i tak dałeś już mega długą wędkę, dzięki!

0
Pinek napisał(a):

Kurczę wiesz co, ciężko mi teraz ci podpowiadać krok po kroku - spróbuj najpierw Zunionować pierwszy select z drugim, bez dodatkowego ordera. Tak btw. to widzę że chyba Postgresa używasz?

Kurdę Uniony działają, ale sypie mi się jak chce zorderować tą drugą część ;(

0

A samo

SELECT * FROM tabela WHERE ID BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR) ASC, CAST(ID AS VARCHAR) ASC

działa? Jeśli tak, to może spróbuj opakować to jeszcze:

SELECT * FROM (SELECT * FROM tabela WHERE ID BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR) ASC, CAST(ID AS VARCHAR) ASC)
0
Pinek napisał(a):

A samo

SELECT * FROM tabela WHERE ID BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR) ASC, CAST(ID AS VARCHAR) ASC

działa? Jeśli tak, to może spróbuj opakować to jeszcze:

SELECT * FROM (SELECT * FROM tabela WHERE ID BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR) ASC, CAST(ID AS VARCHAR) ASC)

W sumie w tym jest problem, że nie działa. Przy pierwszej komendzie wyskakuje: Operand type clash: text is incompatible with smallint

0

No czyli problem z castami. A po co ty ich używasz w ogóle, skoro wszędzie masz liczby? :D

0
Pinek napisał(a):

No czyli problem z castami. A po co ty ich używasz w ogóle, skoro wszędzie masz liczby? :D

Kombinuję :D

SELECT * FROM tabela WHERE ID BETWEEN 400 AND 408 ORDER BY Typ ASC, ID ASC

To też nie działa i daje ten sam komunikat :D

0

Dziwne. Jakiego typu jest kolumna Typ? Na szybko testowałem na
https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_in

i np zapytanie

SELECT * FROM [Orders] ORDER BY CustomerID ASC, EmployeeID ASC

działa bez zastrzeżeń (czy to sortowanie po numerze czy po varcharze)

0
Pinek napisał(a):

Dziwne. Jakiego typu jest kolumna Typ? Na szybko testowałem na
https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_in

i np zapytanie

SELECT * FROM [Orders] ORDER BY CustomerID ASC, EmployeeID ASC

działa bez zastrzeżeń (czy to sortowanie po numerze czy po varcharze)

Typu text

0

Typ text to raczej przestarzały typ, lepiej VARCHAR lub VARCHAR2 (jeśli twoja baza go obsługuje)

0
Pinek napisał(a):

Typ text to raczej przestarzały typ, lepiej VARCHAR lub VARCHAR2 (jeśli twoja baza go obsługuje)

Zostawiłem na text, ale poprawiłem na:

SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR)

i działa, ale jeżeli chce użyć całości

SELECT * FROM tabela WHERE ID BETWEEN 005 AND 399
UNION
SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR)
UNION
SELECT * FROM tabela WHERE ID BETWEEN 409 AND 999

to mam błąd: > Msg 156, Level 15, State 1, Line 4
Incorrect syntax near the keyword 'UNION'.

0

A spróbuj wybierać tylko id póki co (ID zamiast *), i we wszystkich 3 podzapytaniach konwertuj ID w takim razie: WHERE CONVERT(VARCHAR,ID) BETWEEN

0
Pinek napisał(a):

A spróbuj wybierać tylko id póki co (ID zamiast *), i we wszystkich 3 podzapytaniach konwertuj ID w takim razie: WHERE CONVERT(VARCHAR,ID) BETWEEN

Próbowałem, efekt taki sam:

Incorrect syntax near the keyword 'UNION'.

Sama komenda:

SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR)

działa. Union bez ordera też działa:

SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 005 AND 399
UNION ALL
SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408
UNION ALL
SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 409 AND 999

Sypie się jak to połączę.

0

Dobra, pominąłem jedną ważną rzecz. Mianowicie ORDER BY musi być zawsze na końcu zapytania. Dlatego owrapuj jeszcze środkowe podzapytanie. Czyli zamiast

SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR)

daj

SELECT * FROM (SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR))
0
Pinek napisał(a):

Dobra, pominąłem jedną ważną rzecz. Mianowicie ORDER BY musi być zawsze na końcu zapytania. Dlatego owrapuj jeszcze środkowe podzapytanie. Czyli zamiast

SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR)

daj

SELECT * FROM (SELECT * FROM tabela WHERE CONVERT(VARCHAR,ID) BETWEEN 400 AND 408 ORDER BY CAST(Typ AS VARCHAR), CAST(ID AS VARCHAR))

Otrzymałem komunikat:

The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.

0

Kurde :D No już się poddaję tak ci zdalnie pomagać. Na https://www.w3schools.com/sql/trysql.asp?filename=trysql_op_in działa np takie zapytanie nawet:

SELECT * FROM (SELECT CustomerID FROM [Orders] WHERE EmployeeID < 2 ORDER BY CustomerID ASC, EmployeeID ASC)
UNION ALL
SELECT * FROM (SELECT CustomerID FROM [Orders] WHERE EmployeeID < 2 ORDER BY CustomerID ASC, EmployeeID ASC)
UNION ALL
SELECT * FROM (SELECT CustomerID FROM [Orders] WHERE EmployeeID < 2 ORDER BY CustomerID ASC, EmployeeID ASC)

Jedyne co mogę poradzić to krok po kroku eliminować kolejne errory, bo to na pewno da się zrobić ;)

0

laNie potrzebujesz uniona, przetestuj to:

Dane (wrzuciłbym na fiddle, ale nie działa):

CREATE TABLE tabela
    ([pole] int)
;
    
INSERT INTO tabela
    ([pole])
VALUES
    (005),    (006),    (100),    (300),    (400),    (401),    (402),    (403),    (404),    (405),    (406),    (407),    (408),    (400),    (401),    (402),    (403),    (404),    (405),    (406),    (407),    (408),    (700);

Zapytanie:


select 
    * 
from (select 
	   case 
		  when pole between 0 and 399 then 1
		  when pole between 400 and 408 then 2
		  else 99 
	   end grupa,
	   ROW_NUMBER() over (PARTITION by pole order by pole) r,
	   pole 
    from 
	   tabela) dt
order by 
    grupa
    ,r
    ,pole

1 użytkowników online, w tym zalogowanych: 0, gości: 1