webForumDet fria alternativet

Sql fråga som inte fungerar med Where clause??

9 svar · 1 667 visningar · startad av evilaid

evilaidMedlem sedan apr. 2009433 inlägg
#1

Hej,

Min kompetens om SQl är väldigt begränsade och antagligen ligger problemet där för jag kan inte se varför denna inte skall fungera..

Så fort jag lägger till en where clause så står det bara och tuggar när jag kör den i Sql manager.

Första exemplet här fungerar kanon

Select f.file_id, c.company,c.id, cf.filename, cf.updatetime, sr.server_id, s.server_name, at.app_type as app, aa.app_action as appAction,MAX(run_time) as serverRunTime, 
				(select top(1) last_reg from st_filereadings stf2 where stf2.file_id= f.file_id and stf2.server_id = f.server_id order by last_reg desc	) as max_last_reg,	
				(select top(1) stf3.status	from st_filereadings stf3 where stf3.file_id= f.file_id and stf3.server_id = f.server_id order by last_reg desc	) as current_status, 
				(select top(1) stf4.update_time from st_filereadings stf4 where stf4.file_id= f.file_id and stf4.server_id = f.server_id order by update_time desc	) as app_update 
				from st_filereadings f left join st_customer_files cf ON cf.id = f.file_id left join st_customers c ON c.id = cf.customer_id left join st_customer_groups cg ON cg.id = cf.customer_id 
				left join st_servers s ON s.id = f.server_id Left join st_serverreadings sr ON sr.server_id = f.server_id Left join st_app_type at ON at.id = f.app_type Left join st_app_action aa ON aa.id = f.app_action 
			
				group by f.file_id, c.company,c.id, cf.filename, cf.updatetime, f.server_id,s.server_name, sr.server_id,at.app_type, aa.app_action 
				Order by c.Company, s.server_name, at.app_type,app_update

Nu när jag bara lagt på "Where cf.dashboard=1" så tuggar det bara..

Select f.file_id, c.company,c.id, cf.filename, cf.updatetime, sr.server_id, s.server_name, at.app_type as app, aa.app_action as appAction,MAX(run_time) as serverRunTime, 
				(select top(1) last_reg from st_filereadings stf2 where stf2.file_id= f.file_id and stf2.server_id = f.server_id order by last_reg desc	) as max_last_reg,	
				(select top(1) stf3.status	from st_filereadings stf3 where stf3.file_id= f.file_id and stf3.server_id = f.server_id order by last_reg desc	) as current_status, 
				(select top(1) stf4.update_time from st_filereadings stf4 where stf4.file_id= f.file_id and stf4.server_id = f.server_id order by update_time desc	) as app_update 
				from st_filereadings f left join st_customer_files cf ON cf.id = f.file_id left join st_customers c ON c.id = cf.customer_id left join st_customer_groups cg ON cg.id = cf.customer_id 
				left join st_servers s ON s.id = f.server_id Left join st_serverreadings sr ON sr.server_id = f.server_id Left join st_app_type at ON at.id = f.app_type Left join st_app_action aa ON aa.id = f.app_action 
				where cf.dashboard = '1' 
				group by f.file_id, c.company,c.id, cf.filename, cf.updatetime, f.server_id,s.server_name, sr.server_id,at.app_type, aa.app_action 
				Order by c.Company, s.server_name, at.app_type,app_update

Som synes så har jag precis lärt mig Subselect :)
Vet att det kanske inte ät rätt sätt att använda men det har fungerat bra och det enda jag vill uppnå är att bara plocka alla läsningar där dashboard fältet är satt till true.

Huvudtabellen är st_filereadings där jag hämtar den senaste avläsningar och kopplar på lite stödtabeller...
Mvh

nitro2k01Medlem sedan aug. 20039 342 inlägg
#2

Orkar inte sätta mig in i hela frågan, men prova att inner join:a st_customer_files istället för left join.

from st_filereadings f inner join st_customer_files cf ON ...
evilaidMedlem sedan apr. 2009433 inlägg
#3

Ska testa det, tack för tipset :)

evilaidMedlem sedan apr. 2009433 inlägg
#4

Nu fick jag möjlighet att testa det men det hjälpte tyvärr inte med inner join..
Mitt fält för dashboard har datatype: Bit.. Men det borde väll inte vara något konstigt?

pebiMedlem sedan jan. 2005327 inlägg
#5

Är det mySQL? För isåfall är ju inte bit, det du vill ha.
I mySQL är väl en bit, en byte typ.
DVS 8 st ettor eller nollr.

http://dev.mysql.com/doc/refman/5.7/en/bit-type.html

Så är det mysql borde du väl vilja ha datatypen bool.
Och jämföra med true.

Och är det sql-server du använder.
Så kan jag tänka mig att null värden ställer till det.
En bit i sql-server kan ju ha 1,0 eller null
http://msdn.microsoft.com/en-us/library/ms177603.aspx
Så om det är sql-server, vad händer om du skriver villkoer som dashboras is not null?

Så vilken DB är det, och vad har du för värde lagrat i dashborad?

evilaidMedlem sedan apr. 2009433 inlägg
#6

Ber om ursäkt, klickade faktiskt på fel tråd och hamnade i den klistrade för Riktlinjer :)

Första eller andra punktert var att ange Databas.. My bad.

Detta är MSSQL version 10.0.55
Det är faktikst som du säger att det finns Null värden på vissa rader..
Ska testa ditt villkor :)

tack

evilaidMedlem sedan apr. 2009433 inlägg
#7

Tyvärr hjälpte det inte utan det står och tuggaR även med is not null..

Får det stå tillräckligt länge så kommer det med det handlar om många minuter, så det känns som att databasen loopar ihjäl sig :)

1:49 min tog det att ställa frågan innan resultatet kom nu..
st_filereadings innehåller 65 000 rader

pebiMedlem sedan jan. 2005327 inlägg
#8

OK,
Då var det ju en annan femma.
Om du faktiskt får ett svar, som verkar korrekt, efter bortåt 2 min.
Då är det ju en fråga om prestanda.
Och då måste man nog verkligen sätta sig in i din fråga ordentligt.
Subquerys är väl generellt sett ganska långsamma.

Så antingen får du väl tänka, och se om det går att lösa på annat sätt.

Det kanske ev. går att öka prestanda genom att indexera tabellerna bättre?
Kolla vilka index sql-server tycker saknas.
(tips finns t.ex här: http://msdn.microsoft.com/en-us/library/ms345405(v=sql.105).aspx
)

evilaidMedlem sedan apr. 2009433 inlägg
#9

Ska kolla på du länkade, men är detr rimligt att man kan få prestanda problem med en huvudtabell som endast har 65 000 rader? Eller är det så att koden är katastrofalt felaktig..

Även med dålig kod så känns 65 k rader som ganska lite eller?

aasahMedlem sedan mars 20034 471 inlägg
#10

evilaid skrev:

Ska kolla på du länkade, men är detr rimligt att man kan få prestanda problem med en huvudtabell som endast har 65 000 rader? Eller är det så att koden är katastrofalt felaktig..

Även med dålig kod så känns 65 k rader som ganska lite eller?

Det beror på hur dålig... Men det beror även på hur mycket plats dina 65000 rader tar, hur många rader det är i de andra tabellerna, vad du har för index mm. Prestandafrågor är nästan alltid komplexa.

Ett antal kontrollfrågor:
Har alla dina tabeller PRIMARY KEYs?
Har du FOREIGN KEY index på alla relevanta ställen? Annars kan JOINer ta en evighet.

Om svaret är NEJ på någon av de frågorna har du anledning att fundera över varför och huruvida det är en del av problemet.

Men även om svaret är JA på båda frågorna gör du en himla massa onödigt jobb i den frågan.

För det första bör man i normalfallet undvika subfrågor. (Ja, det finns lägen där de behövs och är en smidig lösning, men i allmänhet är det en prestandabov med stort P.)

I en SQL fråga kommer varje subfråga att köras om en gång per rad i den stora (sammanslagna) tabellen där den används. Detta är med största sannolikhet inte vad du vill. På samma sätt går det alltid fortare om man begränsar antalet intressanta rader så mycket som möjligt innan man slår ihop tabeller eller använder aggregerande funktioner. Ju färre data, ju snabbare exekvering.

Om vi indenterar din fråga så den blir läsbar så har du:

Select 
	f.file_id, 
	c.company,
	c.id, 
	cf.filename, 
	cf.updatetime, 
	sr.server_id, 
	s.server_name, 
	at.app_type as app, 
	aa.app_action as appAction,
	MAX(run_time) as serverRunTime, 
	(	
		select top(1) 
			last_reg 
		from 
			st_filereadings stf2 
		where 
			stf2.file_id= f.file_id and 
			stf2.server_id = f.server_id 
		order by 
			last_reg desc	
	) as max_last_reg,
	(
		select top(1) 
			stf3.status	
		from 
			st_filereadings stf3 
		where 
			stf3.file_id= f.file_id and 
			stf3.server_id = f.server_id 
		order by 
			last_reg desc	
	) as current_status, 
	(
		select top(1) 
			stf4.update_time 
		from 
			st_filereadings stf4 
		where 
			stf4.file_id= f.file_id and 
			stf4.server_id = f.server_id 
		order by 
			update_time desc	
	) as app_update 
from 
	st_filereadings f 
	left join st_customer_files cf ON 
		cf.id = f.file_id 
	left join st_customers c ON 
		c.id = cf.customer_id 
	left join st_customer_groups cg ON 
		cg.id = cf.customer_id 
	left join st_servers s ON 
		s.id = f.server_id 
	Left join st_serverreadings sr ON 
		sr.server_id = f.server_id 
	Left join st_app_type at ON 
		at.id = f.app_type 
	Left join st_app_action aa ON 
		aa.id = f.app_action 
where 
	cf.dashboard = '1' 
group by 
	f.file_id, 
	c.company,
	c.id, 
	cf.filename, 
	cf.updatetime, 
	f.server_id,
	s.server_name, 
	sr.server_id,
	at.app_type, 
	aa.app_action 
Order by c.Company, s.server_name, at.app_type,app_update

Om vi börjar med att titta på dina två första subfrågor så ser vi att de tar ut två olika kolumner från samma tabell och samma rad i den tabellen.

Du bör se till att bara gör detta en gång istället för 65000 ggr minst för huvudtabellens alla rader. Lagra den infon för sig i en temptabell eller CTE, och använd denna via en JOIN istället.

Sedan, till vilken tabell hör kolumnen run_time i den yttersta frågan? Det är den enda utan tabellalias ovan. Måste du verkligen JOINa alla dessa tabeller innan du vet vilka rader som har MAX(run_time)?

Vad är det frågan är tänkt att svara på, om du ställer den i ord?

130 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
128 ms — hämta tråd, inlägg och bilagor (db)