webForumDet fria alternativet

SQL fråga som jag inte riktigt får ihop

Databaser & SQL

7 svar · 1 426 visningar · startad av just me

Medlem sedan maj 200145 inlägg
Frågan#1

Hej

Jag vill få ut hur många kontroller som är gjorda under ett visst antal månader. Detta fungerar utmärkt ifall jag enbart väljer en månad. Men om jag tar ett antal månader funkar det inte alls utan då får jag ett felmeddelande. Jag är rätt ny i detta!! Kan någon ta en titt och säga vad jag gör för fel. Detta ska användas i en SSRS. Tack på förhand.

Fel:et
Msg 512, Level 16, State 1, Line 12
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

SQL:EN
DECLARE @FranManad as int
DECLARE @TillManad as int
DECLARE @Line as int
DECLARE @Ar as int
SET @FranManad = 8
SET @TillManad=10
SET @Line=100
SET @Ar =2012

Select distinct map, (DATEPART(mm,MEAS_DATETIME)) as manad,(DATEPART(yy,MEAS_DATETIME)) as ar,sum(FCOUNT) as sumantalfel,max(tolerans) as tolerans

,(select sum(count_c) as antalkont from kvalite.dbo.MainImport where
DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and (fcode = '0') and map like @Line
and (DATEPART(yy,MEAS_DATETIME))=@Ar group by DATEPART(yy,MEAS_DATETIME),DATEPART(mm,MEAS_DATETIME),map) as Count_C
,(select sum(count_p) as antalkont from kvalite.dbo.MainImport where
DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and (fcode = '0') and map like @Line
and (DATEPART(yy,MEAS_DATETIME))=@Ar group by DATEPART(yy,MEAS_DATETIME),DATEPART(mm,MEAS_DATETIME),map) as Count_P

from kvalite.dbo.MainImport inner join kvalite.dbo.FelTolerans ON MainImport.FCODE = FelTolerans.FCODET
where DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and (fcode='P25.4.1') and map like @Line
and (DATEPART(yy,MEAS_DATETIME))=@Ar group by DATEPART(yy,MEAS_DATETIME),DATEPART(mm,MEAS_DATETIME),map
Medlem sedan juli 2003555 inlägg
#2

Jag formaterade sql-frågan ( http://www.dpriver.com/pp/sqlformat.htm ) för att försöka begripa den, och det jag tror är problemet är att du har två subqueries Count_C och Count_P som förväntas ge varsitt värde. Om jag förstår rätt så retunerar de frågorna dock flera värden då de använder sig av group by

Medlem sedan maj 200145 inlägg
#3

Ok

Ja precis men jag vill att den ska kunna retunera flera värden. Eftersom SSRS enbart kan hantera en SQL sats per graf.

/Erik

Medlem sedan juli 2003555 inlägg
#4

Om vi säger såhär: Om du skulle försöka tolka frågan för hand, hur har du tänkt dig att den ska fungera?

Jag tror att du ska ta och ta bort din group by i dina subqueries och enbart ha den i den yttre, sedan lägger du till where-villkor i de inre som motsvarar dina group by.

Medlem sedan maj 200145 inlägg
#5

Hej

Hej

Jag har testat att ta bort group by i sub. Men då kommer samma värde ifrån subqueries. Men då får jag samma värde på dessa på varje rad. Och inte att det sorteras på månad för månad.

typ

Map månad felantal Count_C(Sub1) Count_P(Sub2)
100 8 10 1300 80
100 9 30 1300 80
100 10 40 1300 80

Men det jag vill ha är

Map månad felantal Count_C(Sub 1) Count_P (Sub2)
100 8 10 400 20
100 9 30 200 30
100 10 40 300 40

/Erik

Medlem sedan juli 2003555 inlägg
#6

Du läste nog inte hälften av det jag skrev ;) Citerar mig själv:

"ta bort din group by i dina subqueries och enbart ha den i den yttre, sedan lägger du till where-villkor i de inre som motsvarar dina group by"

Du gjorde nog bara det som stod innan komma-tecknet, då är det inte så konstigt :) (Sen exakt hur det ser ut vet jag inte, men det är en annan femma.. :) )

Medlem sedan mars 20034 471 inlägg
#7

Din SELECT-sats blir, om den indenteras så man ser vad 17 du håller på med, följande:

Select distinct 
	map, 
   (DATEPART(mm,MEAS_DATETIME)) as manad,   
   (DATEPART(yy,MEAS_DATETIME)) as ar,
   sum(FCOUNT) as sumantalfel,
   max(tolerans) as tolerans,
   (
		select sum(count_c) as antalkont 
		from kvalite.dbo.MainImport 
		where
			DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and 
			(fcode = '0') and 
			map like @Line and 
			(DATEPART(yy,MEAS_DATETIME))=@Ar 
		group by 
			DATEPART(yy,MEAS_DATETIME),
			DATEPART(mm,MEAS_DATETIME),
			map
	) as Count_C,
	(
		select sum(count_p) as antalkont 
		from kvalite.dbo.MainImport 
		where
			DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and 
			(fcode = '0') and 
			map like @Line and 
			(DATEPART(yy,MEAS_DATETIME))=@Ar 
			group by 
				DATEPART(yy,MEAS_DATETIME),
				DATEPART(mm,MEAS_DATETIME),
				map
	) as Count_P
from 
	kvalite.dbo.MainImport 
	inner join kvalite.dbo.FelTolerans ON MainImport.FCODE = FelTolerans.FCODET
where 
	DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and 
	(fcode='P25.4.1') and 
	map like @Line and 
	(DATEPART(yy,MEAS_DATETIME))=@Ar 
group by 
	DATEPART(yy,MEAS_DATETIME),
	DATEPART(mm,MEAS_DATETIME),
	map

Det första man kan konstatera är att din tre GROUP BY alla ser likadana ut och att det enda som skiljer Count_C och Count_P är vilken kolumn du räknar värden i.

För att slippa beräkna precis samma GROUP BY i dina två inre uttryck är det bättre att använda en temporär tabell att mellanlagra resultat i:

select 
	DATEPART(yy,MEAS_DATETIME) as MeasYear,
	DATEPART(mm,MEAS_DATETIME) as MeasMonth,
	map,
	sum(count_c) as antalC,
	sum(count_p) as antalP
INTO #AntalCP	 
from kvalite.dbo.MainImport 
where
	DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and 
	(fcode = '0') and 
	map like @Line and 
	(DATEPART(yy,MEAS_DATETIME))=@Ar 
group by 
	DATEPART(yy,MEAS_DATETIME),
	DATEPART(mm,MEAS_DATETIME),
	map

Select distinct 
	MI.map, 
   DATEPART(mm,MI.MEAS_DATETIME) as manad,   
   DATEPART(yy,MI.MEAS_DATETIME) as ar,
   sum(FCOUNT) as sumantalfel,
   max(tolerans) as tolerans,
   A.CountC as Count_C,
   A.CountP as Count_P
from 
	kvalite.dbo.MainImport MI
	inner join #AntalCP A ON 
		MI.DATEPART(mm,MEAS_DATETIME) = A.MeasYear AND
		MI.DATEPART(yy,MEAS_DATETIME) = A.MeasMonth AND
		MI.map = A.map
	inner join kvalite.dbo.FelTolerans FT ON 
		MI.FCODE = FT.FCODET
where 
	MI.fcode='P25.4.1' -- Se nedan *
group by 
	DATEPART(yy,MI.MEAS_DATETIME),
	DATEPART(mm,MI.MEAS_DATETIME),
	MI.map,
	A.CountC,
	A.CountP
	
DROP TABLE #AntalCP

* - Din ursprungs-WHERE säger:

	
        DATEPART(mm,MEAS_DATETIME) between @FranManad and @TillManad and  -- 1
	(fcode='P25.4.1') and  -- 2 
	map like @Line and  -- 3
	(DATEPART(yy,MEAS_DATETIME))=@Ar -- 4

1, 3 och 4 - är exakt samma krav som du redan satt i den temporära tabellen. I själva frågan gör du en inre join mot temptabellen, där du kräver att MI:s år, månad och map-värden ska matcha temptabellens där dessa villkor redan gäller, så de här villkoren finns kvar implicit.

Om din användare INTE får skapa temporära tabeller så får du istället lägga uträkningen av CountC och CountP i en (och samma) subtabell i FROM, vilket åtminstone gör att du inte behöver använda GROUP BY mer än en gång för dessa två värden.

onkelborg - ditt tips funkar bara om den inre joinen mot Feltolerans inte någonstans skapar dubblettrader ihop med MainImport, vilket den mycket väl kan göra.

Medlem sedan maj 200145 inlägg
#8

AAA Tack

Hej

Tack så jätte mycket aasah och ni andra för att ni hjälpte mig att lösa problemet. Din kod fungerade kanon det var bara lite små grejor sedan funkade allt.!!!!!

/Erik

263 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
129 ms — deklarationer (db)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)
123 ms — ändringar (db)