łączenie w jeden raport wielokrotnego zapytanie do tej samej tabeli

0

Witam wszystkich!

Otóż mam tabelę na SQL Express, która ma strukturę mniej więcej taką

ID - int
LUD - datetime
WADA_1 - bit
WADA_2 - bit
..
WADA_N - bit

jest to log z maszyny produkcyjnej.

Potrzebuję wykonać raport, który pogrupuje i policzy wady o wartości 1 dla poszczególnych tygodni w roku

ROK | TYDZIEŃ | WADA_1 | WADA_2 | ... | WADA_N |

Jak to zrobić?

1
set datefirst 1; -- w zależnosci od ustawien jezyka

SELECT ID, datepart(week, LUD) WK, 
SUM(CASE WHEN  WADA_1 = 1 THEN 1 ELSE 0 END) W1,
SUM(CASE WHEN  WADA_2 = 1 THEN 1 ELSE 0 END) W2,
...
SUM(CASE WHEN  WADA_n = 1 THEN 1 ELSE 0 END) Wn
GROUP BY ID, datepart(week, LUD)
0

Dzięki, ale wywala mi taki błąd

Msg 4145, Level 15, State 1, Line 4
An expression of non-boolean type specified in a context where a condition is expected, near 'THEN'.

Zapytanie jakie wpisałem
SET datefirst 1; -- w zależnosci od ustawien jezyka

SELECT ID, datepart(week, LUD) WK,
SUM(CASE WHEN LeftCapNotOK THEN 1 ELSE 0 END) LC,
SUM(CASE WHEN LeftMgoCtrlNotOK THEN 1 ELSE 0 END) LMg,
SUM(CASE WHEN LeftCenteringNotOK THEN 1 ELSE 0 END) LCe
from dbo.T_DATALOG_MASTER
GROUP BY ID, datepart(week, LUD)

0

Sorki, =1 nie wpisałem.
Teraz działa, choć wyniki są inne niż przy pojedynczym zapytaniu dla poszczególnych parametrów. Potestuję to się odezwę.
Dzięki za pomoc.

0

A gdzie masz warunek spełniający ? "WHEN LeftCapNotOK " jest równe co ?? żeby wstawił 1 jeśli spełnione a 0 jak nie ?
Spójrz na mój przykład dokładnie .. i może poczytaj o CASE tak w ogóle ;)

Edit: Nooo własnie ;)

0

No i mam taką sytuację

**Zapytanie nr 1 **
SELECT datepart(yy,lud) as Rok, datepart(ww, LUD) as Tydzień,
SUM(CASE WHEN LeftCenteringNotOK=1 or RightCenteringNotOK=1 THEN 1 ELSE 0 END) Centrowanie_Braki
from dbo.T_DATALOG_MASTER
GROUP BY datepart(yyyy,lud), datepart(week, LUD)
order by Rok, Tydzień

Wynik:
Rok Tydzień Centrowanie_Braki
2018 4 687
2018 5 307
2018 6 81
**
Zapytanie nr 2**
SELECT DATEPART(YYYY, LUD) AS Year, DATEPART(ww, LUD) AS Week, COUNT(ID) AS Centering_scrap
FROM dbo.T_DATALOG_MASTER
WHERE (LeftCenteringNotOK = 1) OR (RightCenteringNotOK = 1)
GROUP BY DATEPART(YYYY, LUD), DATEPART(ww, LUD)

Wynik:
Year Week Centering_scrap
2018 4 613
2018 5 330
2018 6 131

Skąd rozbieżności? Teoretycznie COUNT i SUM powinny policzyć to samo...

0
BlackBad napisał(a):

Spójrz na mój przykład dokładnie .. i może poczytaj o CASE tak w ogóle ;)

No właśnie poczytałem i dlatego wywaliłem =1 :) Zła interpretacja z mojej strony wyrażenia * Boolean_expression * z helpa. No cóż czytać to trzeba umić ;)

0

Skąd rozbieżności? Teoretycznie COUNT i SUM powinny policzyć to samo...

No to pojechałeś ...
No ale skoro pytasz ... to Ci odpowiem. W pierwszym zapytaniu robisz selecta z całej tabeli, grupujesz i jeśli jakiś tam warunek jest spełniony to dajesz 1 lub 0, potem sumujesz wszystkie rekordy, W drugim zapytaniu robisz selecta do części tabeli WHERE (LeftCenteringNotOK = 1) OR (RightCenteringNotOK = 1) i zliczasz ilość wystąpień

0

Witam jestem początkujący
ale czy nie wystarczyło by
select to_char((Lud,'YYYY'), to_char((Lud,'WW'), sum(wada_1), from tabela
where wada_1 =1
group by to_char((Lud,'YYYY'), to_char((Lud,'WW')

pisane pod oracle i na szybko ale chodzi mi bardziej o logikę
posortuje nam najpierw tam gdzie jwada_1 = 1
a potem pogrupuje po roku i tyg

0

po pierwsze nie posortuje bo od sortowania jest opcja order by, po drugie nie do końca bo logika w oracle jest trójwartościowa czyli 0, 1 i null. Nie pamiętam dokładnie jak się to zachowa w przypadku null ale nie ważne. Jeśli zrobisz where wada_1 = 1 to pominiesz wszystkie rekordy gdzie wada_1 <> 1 czyli np wada_1 = 2. Różnica między sum i count jest taka, że jeśli masz wada_1 = 1 i wada_1 = 2 to sum zwróci Ci 3, a count zwróci Ci 2. Nie do końca rozumiem czy chcesz zliczyć sumę wszystkich wada_1 z całej tabeli czy chcesz mieć ilość wystąpień wada_1 = 1. Nie mniej jednak oracle ma rewelacyjne funkcje okienkowe do raportów jak cube, rollup czy grouping sets ale to już nieco wyższa szkoła jazdy. I NAJWAŻNIEJSZE FORMATUJ KOD!!!!!

0

a dobra to ja źle zrozumiałem zapytanie na pierwszym poście
czyli 1 może wystąpić w wada_1 wada_2 wada_n
w takim razie musi być sprawdzenie

0
woolfik napisał(a):

Skąd rozbieżności? Teoretycznie COUNT i SUM powinny policzyć to samo...

No to pojechałeś ...
No ale skoro pytasz ... to Ci odpowiem. W pierwszym zapytaniu robisz selecta z całej tabeli, grupujesz i jeśli jakiś tam warunek jest spełniony to dajesz 1 lub 0, potem sumujesz wszystkie rekordy, W drugim zapytaniu robisz selecta do części tabeli WHERE (LeftCenteringNotOK = 1) OR (RightCenteringNotOK = 1) i zliczasz ilość wystąpień

Wydaje mi się, że różnicę między COUNT i SUM to jeszcze w miarę ogarniam ;)
Nie rozumiem natomiast dlaczego zapytania dają inny wynik skoro w obu chcę zliczać te wystąpienia w których WADA_1 lub WADA_2 jest równa 1? Bo nie sądzę aby problemem był przypadek gdy obie wady mają wartość 1..

0

Jestem początkujący, ale takich rzeczy mi nie tłumaczcie 😁 Ja to rozumiem.
Problem w tym, że ja sumuję pola typu bit, a one mogą mieć wartość 0 lub 1. Poza tym w warunku podaję, że chcę zsumować tylko pola o wartości 1. Ten sam warunek podaję dla Count. Czemu więc mam inny wynik?

0

Pokaż kod dla 1 i 2 (sformatowany!) i może przykładowe dane...

0
Marian napisał(a):

Jestem początkujący, ale takich rzeczy mi nie tłumaczcie 😁 Ja to rozumiem.
Problem w tym, że ja sumuję pola typu bit, a one mogą mieć wartość 0 lub 1. Poza tym w warunku podaję, że chcę zsumować tylko pola o wartości 1. Ten sam warunek podaję dla Count. Czemu więc mam inny wynik?

Masakra z każdym postem coraz bardziej strzelasz sobie w kolano ... w oracle nie ma czegoś takiego jak BIT tego typu pole występuje w MSSQL. Natomiast oracle posiada trójwartościową logikę czyli 0, 1 i NULL. W tym momencie napiszę też pewnie oczywistą dla Ciebie rzecz ALE 0 i NULL to nie to samo dla bazy oracle ... póki nie pokażesz struktury tabel to nie będę w stanie podać dokładnej odpowiedzi dlaczego ale na to co napisałeś wydaje mi się, że przyczyną jest to, że do zapytania wpada inny zakres rekordów więc i suma jest inna.

0

Witam po weekendzie :)

Dzięki za wszystkie uwagi

woolfik
Mówimy o SQL Express. Nowy wspominał o Oracle
Lubię swoje kolana i nie zwykłem do nich strzelać - NULL i 0 rozróżniam.
Nie, nie jest to projekt studencki - dostaliśmy maszynę z dedykowaną bazą danych, a że zasobów w postaci informatyka od baz danych w firmie brak - sam rzeźbię (jestem inżynierem produkcji).

BlackBad
Struktura tabeli i zapytania - poniżej.
Tabele z wynikami umieściłem pod zapytaniami
(tydzień 6 usunąłem ponieważ zmieniał się z godziny na godzinę, bo maszyna cały czas produkuje).

Tak więc dzisiaj oba zapytania generują ten sam wynik, co z jednej strony mnie cieszy, bo tego oczekiwałem. Z drugiej strony - nie wiem dlaczego :(

Struktura tabeli T_Datalog_Master:

Column Name Data Type Allow Nulls
ID int Unchecked
LOT varchar(30) Unchecked
SERIAL_NUMBER varchar(30) Unchecked
LUD datetime Unchecked
ScrapResistance bit Checked
LeftMgoDepth int Checked
RightMgoDepth int Checked
LeftCapSize int Checked
RigthCapSize int Checked
LeftOhmTestDone bit Checked
LeftOhmTestNotOK bit Checked
LeftInsTestDone bit Checked
LeftInsTestNotOK bit Checked
LeftR2TestDone bit Checked
LeftR2TestNotOK bit Checked
LeftR1TestDone bit Checked
LeftR1TestNotOK bit Checked
LeftCapDone bit Checked
LeftCapNotOK bit Checked
LeftConingDone bit Checked
LeftConingNotOK bit Checked
LeftMgoCtrlDone bit Checked
LeftMgoCtrlNotOK bit Checked
LeftCleaningDone bit Checked
LeftCleaningNotOK bit Checked
LeftCenteringDone bit Checked
LeftCenteringNotOK bit Checked
LeftCutDone bit Checked
LeftPinCtrlDone bit Checked
LeftPinCtrlNotOK bit Checked
LeftChamperingDone bit Checked
LeftChamperingNotOK bit Checked
RightOhmTestDone bit Checked
RightOhmTestNotOK bit Checked
RightInsTestDone bit Checked
RightInsTestNotOK bit Checked
RightR2TestDone bit Checked
RightR2TestNotOK bit Checked
RightR1TestDone bit Checked
RightR1TestNotOK bit Checked
RightCapDone bit Checked
RightCapNotOK bit Checked
RightConingDone bit Checked
RightConingNotOK bit Checked
RightMgoCtrlDone bit Checked
RightMgoCtrlNotOK bit Checked
RightCleaningDone bit Checked
RightCleaningNotOK bit Checked
RightCenteringDone bit Checked
RightCenteringNotOK bit Checked
RightCutDone bit Checked
RightPinCtrlDone bit Checked
RightPinCtrlNotOK bit Checked
RightChamperingDone bit Checked
RightChamperingNotOK bit Checked

Zapytanie pierwsze:

`SET` datefirst 1; -- w zależnosci od ustawien jezyka
 
`SELECT` datepart(yy,lud) as Rok, datepart(ww, LUD) as Tydzień, 
	SUM(CASE WHEN  LeftCenteringNotOK=1 or RightCenteringNotOK=1 THEN 1 ELSE 0 END) Centrowanie_Braki
`FROM` dbo.T_DATALOG_MASTER
`GROUP` `BY` datepart(yyyy,lud), datepart(week, LUD)
`ORDER` `BY` Rok, Tydzień

Wynik zapytania z 8-02 13:35

Rok | Tydzień | Centrowanie_Braki
---------------- | -------------------
2018 | 4 | 687
2018 | 5 | 307

Wynik zapytania z 12-02 8:10

Rok | Tydzień | Centrowanie_Braki
---------------- | -------------------
2018 | 4 | 687
2018 | 5 | 307

Zapytanie drugie:

`SELECT` datepart(yy,lud) as Rok, datepart(ww, LUD) as Tydzień, COUNT(ID) AS Centrowanie_Braki
`FROM` dbo.T_DATALOG_MASTER
`WHERE` (LeftCenteringNotOK=1 or RightCenteringNotOK=1)
`GROUP` `BY` datepart(yyyy,lud), datepart(week, LUD)
`ORDER` `BY` Rok, Tydzień

Wynik zapytania z 8-02 13:36

Rok | Tydzień | Centrowanie_Braki
---------------- | -------------------
2018 | 4 | 613
2018 | 5 | 330

Wynik zapytania z 12-02 8:11

Rok | Tydzień | Centrowanie_Braki
---------------- | -------------------
2018 | 4 | 687
2018 | 5 | 307

1

Nie mam dziś za grosz czasu ... 1 strzał po rzuceniu okiem tylko, dodaj przed 2 zapytaniem tą część:

`SET` datefirst 1;

Ta linijka określa jak są liczone dni tygodnia raz to ustawiasz za drugim razem nie (jest brana wartość domyślna ustawień języka/regionu systemu).

0

BlackBad jesteś wielki!

Dzisiaj znów miałem duże różnice w obu zapytaniach, po wstawieniu sugerowanej linijki - pokazuje to samo.
Serdeczne dzięki.

0

Fajnie, fajnie. To już z kronikarskiego obowiązku napiszmy o co cho.

`SET` datefirst 1; -- oznacza licz tydzień od "Poniedziałku"
`SET` datefirst 7; -- oznacza licz tydzień od "Niedzieli" - i to jest ustawienie domyślne dla US
0

To już sobie doczytałem, ale dzięki. :)

Jeszcze jedno pytanie mi się nasunęło:
Jak ten raport pogrupować nie tylko po tygodniach, ale po dniach i zmianach (6-14, 14-22, 22-6)?

0

Znów CASE i sprawdzenie godziny i ustawienie odpowiedniej wartości:

SET datefirst 1; -- w zależnosci od ustawien jezyka

WITH tempTable as
(
SELECT datepart(yy,lud) as Rok, datepart(ww, LUD) as Tydzień, 
CASE WHEN datepart(hour,lud) BETWEEN 6 and 13 THEN '6-14'
           WHEN datepart(hour,lud) BETWEEN 14 and 21 THEN '14-22' 
           WHEN datepart(HOUR,lud) BETWEEN 22 AND 24 OR datepart(HOUR,lud) BETWEEN 0 AND 5 THEN '22-6'
END as Zmiana,
SUM(CASE WHEN  LeftCenteringNotOK=1 or RightCenteringNotOK=1 THEN 1 ELSE 0 END) Centrowanie_Braki
FROM dbo.T_DATALOG_MASTER
)

SELECT Rok, Tydzień, Zmiana, Centrowanie_Braki FROM tempTable
GROUP BY Rok, Tydzień, Zmiana
ORDER BY Rok, Tydzień, Zmiana
0

Nie mam jak tego dzisiaj przetestować, ale czy to zapytanie nie podaje przypadkiem wyników z "pomieszanej" trzeciej zmiany?
Bo powinno być, że
1 i 2 zmiana przypada na dzień pierwszy,
3 zmiana - od 22-24 - dzień pierwszy, 0-6 dzień drugi itd.
A wydaje mi się, że podane przez Ciebie zapytanie podaje 3 zmianę jako 0-6 dzień pierwszy + 22-24 dzień pierwszy.

0

No więc zapytanie od BlackBad generuje błąd:

Msg 8120, Level 16, State 1, Line 5
Column 'dbo.T_DATALOG_MASTER.LUD' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Twoje, Macin, działa jak należy, tylko nie wiem jak je pożenić z konstrukcją BlackBad. Jak zrobię tak:

SET datefirst 1; -- w zależnosci od ustawien jezyka
 
WITH tempTable AS
(
SELECT LUD data, datepart(year,LUD) rok, datepart(week,LUD) tydzien,
datepart(hour, dateadd(hour,-6,LUD))/8+1 zmiana,
SUM(CASE WHEN LeftCenteringNotOK=1 OR RightCenteringNotOK=1 THEN 1 ELSE 0 END) Centrowanie_Braki
FROM dbo.T_DATALOG_MASTER
)
 
SELECT Rok, Tydzień, Zmiana, Centrowanie_Braki FROM tempTable
GROUP BY Rok, Tydzień, Zmiana
ORDER BY Rok, Tydzień, Zmiana

to wywala taki sam błąd:
Msg 8120, Level 16, State 1, Line 5
Column 'dbo.T_DATALOG_MASTER.LUD' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

1

No jak byk masz napisane, ze nie masz group by...
To group by powinienes miec w temptable. Ale to i tak bedzie źle, bo usilujesz pogrupowac wg roku i tygodnia, a dorzucasz bezsensowna date...
I nie uzywaj PLiterek

1

Dokładnie jak @Marcin.Miga napisał ... generalnie zabierasz się już za troszeczkę bardziej cięższe tematy, a nie rozumiesz podstawowej zasady zapytania SELECT z użyciem funkcji agregujących :|
Tak więc dobrze by było żebyś to chociaż w stopniu podstawowym ogarnął żebyś wiedział co robisz ... na teraz na szybko przesuń klauzule GROUP BY z ostatecznego zapytania do tego tworzącego tempTable (przerabiając kod zrobiłem tu błąd, ze tego nie przesunąłem) i dorzuć kolejną kolumnę po której grupujesz czyli LUD (co jest bez sensu bo zdecyduj sie po czym chcesz grupować wyniki ... po tygodniu czy dacie ? ) albo właśnie usuń z zapytania kolumnę LUD i będzie OK.

0

Rzeczywiście, trochę się pogubiłem, ale już wszystko jasne.
Wygląda jak poniżej i działa jak należy.
Dzięki jeszcze raz za pomoc.

SET datefirst 1; -- w zależnosci od ustawien jezyka
 
WITH tempTable AS
(
select  datepart(year,LUD) AS rok, DATEPART(MM,LUD) AS miesiac, datepart(DD,LUD) AS dzien,
datepart(hour, dateadd(hour,-6,LUD))/8+1 AS zmiana,
SUM(CASE WHEN  LeftCenteringNotOK=1 OR RightCenteringNotOK=1 THEN 1 ELSE 0 END) Centrowanie_Braki
FROM dbo.T_DATALOG_MASTER
GROUP BY datepart(year,LUD), datepart(mm,LUD), datepart(DD,LUD), datepart(hour, dateadd(hour,-6,LUD))/8+1
)
 
SELECT Rok,miesiac,dzien,  Zmiana, Centrowanie_Braki FROM tempTable
ORDER BY Rok,miesiac, dzien, Zmiana
0

Wzniosłem się na wyżyny moich możliwości w temacie SQL. :D
Myślę, że to będzie tak;

SET datefirst 1; -- w zależnosci od ustawien jezyka

WITH tempTable AS
(
select  
	DATEPART(YEAR,DATEADD(YEAR,CASE WHEN (DATEPART(HH,LUD)<6 and DATEPART(dd,LUD)=1 and datepart(mm,lud)=1) THEN -1 ELSE 0 END,lud)) AS rok, 
	DATEPART(MONTH,DATEADD(MONTH,CASE WHEN (DATEPART(HH,LUD)<6 and DATEPART(dd,LUD)=1) THEN -1 ELSE 0 END,lud)) AS miesiac, 
	DATEPART(DAY,DATEADD(DAY,CASE WHEN DATEPART(HH,LUD)<6 THEN -1 ELSE 0 END,lud)) AS DZIEN, 
	DATEPART(hour, dateadd(hour,-6,LUD))/8+1 AS zmiana,
	SUM(CASE WHEN  LeftCenteringNotOK=1 OR RightCenteringNotOK=1 THEN 1 ELSE 0 END) Centrowanie_Braki
FROM dbo.T_DATALOG_MASTER
GROUP BY  
	DATEPART(YEAR,DATEADD(YEAR,CASE WHEN (DATEPART(HH,LUD)<6 and DATEPART(dd,LUD)=1 and datepart(mm,lud)=1) THEN -1 ELSE 0 END,lud)), 
	DATEPART(MONTH,DATEADD(MONTH,CASE WHEN (DATEPART(HH,LUD)<6 and DATEPART(dd,LUD)=1) THEN -1 ELSE 0 END,lud)),
	DATEPART(DAY,DATEADD(DAY,CASE WHEN DATEPART(HH,LUD)<6 THEN -1 ELSE 0 END,lud)), 
	DATEPART(hour, dateadd(hour,-6,LUD))/8+1
)

SELECT Rok,miesiac,dzien,  Zmiana, Centrowanie_Braki 
FROM tempTable
ORDER BY Rok,miesiac, dzien, Zmiana

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