2013-07-31 12 views
8

tak basicially jest 1 pytanie 1 Problem:SQL za pomocą CASE w SELECT z GROUP BY. Potrzebujesz Case-wartość, ale dostać wiersza wartość

1. pytanie - kiedy mam jak 100 kolumn w tabeli (a nie klucz lub uindex jest ustawiony) i Chcę dołączyć do tej tabeli lub dokonać jej podrzędności, czy naprawdę muszę wypisać każdą nazwę kolumny?

2. Problem - Poniższy przykład pokazuje pytanie 1. i mój rzeczywisty problem instrukcja_sql

Przykład:

A.FIELD1, 
(SELECT CASE WHEN B.FIELD2 = 1 THEN B.FIELD3 ELSE null FROM TABLE B WHERE A.* = B.*) AS CASEFIELD1 
(SELECT CASE WHEN B.FIELD2 = 2 THEN B.FIELD4 ELSE null FROM TABLE B WHERE A.* = B.*) AS CASEFIELD2 
FROM TABLE A 
GROUP BY A.FIELD1 

Fabuła jest: jeśli nie stawiać sprawy do własnego oświadczenia select, muszę umieścić rzeczywisty rowname w GROUP BY, a GROUP BY nie grupuje wartości NULL z CASE, ale rzeczywistą wartość z wiersza. I z tego powodu musiałbym albo dołączyć, albo zlikwidować wszystkie kolumny, ponieważ nie ma klucza i nie ma zindeksowania, ani nie znalazłem innego rozwiązania.

DBServer to DB2.

Teraz, aby opisać to tylko słowami i bez SQL: Mam "elementy zamówienia", które można podzielić na "ZD" i "EK" (1 = ZD, 2 = EK) i mogą być pogrupowane według " dystrybutor". Mimo że "elementy zamówienia" mogą mieć jeden z dwóch różnych "działów" (ZD, EK), pola/wiersze dla "ZD" i "EK" są zawsze wypełnione. Potrzebuję zgrupowania, aby rozważyć "departament" i tylko wtedy, gdy zmienia się nazwa "departamentu" (ZD lub EK), wtedy chcę utworzyć nową grupę.

SELECT 
(CASE WHEN TABLE.DEPARTEMENT = 1 THEN TABLE.ZD ELSE null END) AS ZD, 
(CASE WHEN TABLE.DEPARTEMENT = 2 THEN TABLE.EK ELSE null END) AS EK, 
TABLE.DISTRIBUTOR, 
sum(TABLE.SOMETHING) AS SOMETHING, 
FROM TABLE 
GROUP BY 
ZD 
EK 
TABLE.DISTRIBUTOR 
TABLE.DEPARTEMENT 

Ten działał w SELECT i ZD, EK w GROUP BY. Jedynym problemem było to, że nawet jeśli EK nie był wyznaczonym DEPARTEMENTEM, to nadal otwierał on nową grupę, jeśli się zmieniał, ponieważ używał prawdziwej wartości EK, a nie NULL z CASE, jak już wyjaśniałem.

+0

masz na myśli sprawdzenie wartości każdej kolumnie tabeli A do kolumny w tabeli B z tym samym nazwa kolumny i wszystkie kolumny muszą być zgodne? Czy masz na myśli inny rodzaj logiki? – WarrenT

+0

Dokładnie, ale to tylko pytanie, a nie prawdziwy problem, który postaram się dalej/lepiej wyjaśnić w najbliższym czasie. – Khazar

Odpowiedz

6

a tu panie i panowie to rozwiązanie problemu:

SELECT 
(CASE WHEN TABLE.DEPARTEMENT = 1 THEN TABLE.ZD ELSE null END) AS ZD, 
(CASE WHEN TABLE.DEPARTEMENT = 2 THEN TABLE.EK ELSE null END) AS EK, 
TABLE.DISTRIBUTOR, 
sum(TABLE.SOMETHING) AS SOMETHING, 
FROM TABLE 
GROUP BY 
(CASE WHEN TABLE.DEPARTEMENT = 1 THEN TABLE.ZD ELSE null END), 
(CASE WHEN TABLE.DEPARTEMENT = 2 THEN TABLE.EK ELSE null END), 
TABLE.DISTRIBUTOR, 
TABLE.DEPARTEMENT 

@ t-clausen.dk: Dziękuję!

@others: ...

1

Nie, nie ma testu równości przy użyciu symboli wieloznacznych. Będziesz musiał wymienić każde pole, które chcesz przetestować indywidualnie. Jeśli nie chcesz testować poszczególnych pól, możesz użyć haka, np. Połączyć wszystkie pola, np.

WHERE (a.foo + a.bar + a.baz) = (b.foo + b.bar + b.az) 

ale tak czy inaczej, wyświetlasz wszystkie pola.

+1

"+" nie jest operatorem konkatenacji, Twój przykład nie powiedzie się, jeśli istnieje kolumna nieliczbowa. Nawet jeśli użyjesz właściwej konkatenacji, w wielu przypadkach nie będzie działać poprawnie. Na przykład "a" || null || "c" i "a" || "b" || null' będzie zwracać NULL, podczas gdy intencją oczywiście byłoby traktować te kombinacje jako różne. Z drugiej strony jedna wartość NULL nie jest równa innej wartości NULL, więc '' a '|| null || "c" i "a" || null || "c" nie będzie równe, choć intencją w tym przypadku byłoby traktowanie ich jako równych. – mustaccio

+0

Proszę krzyknij na korpusy standardów SQL i powiedz im, aby ustalili standardowego operatora, a następnie ... –

+0

Proszę krzyknij do kogo chcesz. Standard ANSI SQL jasno określa podwójny pionowy pasek jako operator konkatenacji. – mustaccio

2

W rzeczywistości istnieje test równości w postaci wieloznacznej. Nie jestem pewien, dlaczego zgrupowałbyś według pola 1, co wydaje się niemożliwe w twoim przykładzie. Starałem się dopasować go do Twojego pytania:

SELECT FIELD1, 
CASE WHEN FIELD2 = 1 THEN FIELD3 END AS CASEFIELD1, 
CASE WHEN FIELD2 = 2 THEN FIELD4 END AS CASEFIELD2 
FROM 
(
SELECT * FROM A 
INTERSECT 
SELECT * FROM B 
) C 
UNION -- results in a distinct 
SELECT 
A.FIELD1, 
null, 
null 
FROM 
(
SELECT * FROM A 
EXCEPT 
SELECT * FROM B 
) C 

to zawiedzie dla typów danych, które nie są porównywalne

+0

To jest dobra odpowiedź na moje pytanie, ale to smutne, że jest to możliwe tylko w tak zagracony sposób. Teraz tylko problem musi zostać rozwiązany. – Khazar

+0

@Khazar tak, jest to bardzo skomplikowane. Ale chciałem tylko zademonstrować, że było to możliwe –

0

Jeśli trzeba znaleźć wszystkie wiersze w TableA, które odpowiadają w TableB, jak o INTERSECT lub przecinają DISTINCT?

select * from A 
INTERSECT DISTINCT 
select * from B 

Jednakże, jeśli tylko chcesz wierszy z którym cały wiersz odpowiada wartości w wierszu z B, to dlaczego Twój kod przykładowy podjąć pewne wartości z i innych od B? Jeśli wiersz pasuje do wszystkich kolumn, wydaje się to bezcelowe. (Być może twoje pytanie może być wyjaśnione nieco pełniej?)

+0

Problem dotyczy GROUP BY i CASE. Potrzebuję wartości pochodzącej z CASE, ale nie mogę użyć aliasu (co muszę zrobić, ponieważ nie chcę grupować FIELD3, FIELD4 i ich niefiltrowanych wartości), chyba że użyję podselekcji. Tak więc podselekcja jest zwykle bezcelowa, ale nie w tym przypadku. – Khazar

+0

Proszę wyjaśnić wymagania w języku angielskim, w tym (ale nie wyłącznie), co należy zrobić z logiką CASE i logiką dopasowania. Pozostaw program SQL na razie. Możemy to zapewnić, gdy jasno i jednoznacznie zrozumiemy, co trzeba zrobić, – WarrenT

+0

@ t-clausen Niestety, nie wiem, dlaczego nie widziałem twojej odpowiedzi, podczas gdy ja dawałem. – WarrenT

1

może staram się rozwiązać to coś takiego

WITH q as 
(SELECT 
     Department 
    , (CASE WHEN DEPARTEMENT = 1 THEN ZD 
      WHEN DEPARTEMENT = 2 THEN EK 
            ELSE null 
     END) AS GRP 
    , DISTRIBUTOR 
    , SOMETHING 
    FROM mytable 
) 
SELECT 
     Department 
    , Grp 
    , Distributor 

    , sum(SOMETHING) AS SumTHING 
    FROM q 
GROUP BY 
     DEPARTEMENT 
    , GRP 
    , DISTRIBUTOR