Permalänk
Medlem

SQL ninja? (excludera rader)

Jag har två tabeller med en bunke rader. En tabell kan innehålla flera rader som ser likadana ut ( bortsett från ID ). Nu behöver jag en SQL fråga som får ut de rader som finns i min tabell 1 men inte i tabell 2. Problemet är då att om jag har 3 av en radtyp i tabell 1 men bara 2 i tabell 1 så ska jag alltså bara ha ut en som svar.

Man kan säga att det är tabell 1 minus tabell 2 så skulle det gett precis rätt, men tabell 2 kan även innehålla rader som inte finns i tabell 1.

Som ni märkt är jag rätt kass på att förklara men liknande det här:

Tabell 1:
1: a
2: a
3: a
4: b

Tabell 2:
1: b
2: a
3: a
4: o

Så vill jag med frågan få ut en rad:
1: a

Behöver nödvädnigtvis inte en klockren SQL fråga utan mer ett en push i rätt rikning...

Permalänk
Medlem

Du får nog ge ett exempel till på Tabell1/2/svar...

Permalänk
Medlem

har du någon nyckel som kopplar ihop tabellerna?

du kan använda (hoppas det finns i mysql, kan oracle bäst):

where id not in (select id_2 from tabell2)

Permalänk
Medlem

Tabell 1:
1: i
2: i
3: i
4: i

Tabell 2:
1: i
2: i
3: a

Svar:
1: i
2: i

Det dvs det som finns i tabell 1 men inte i tabell 2

Thrawn:
Nej det har jag inte. Det är helt fristående. Tabell två är egentligen en temporär tabell jag har gjort av en lista...Grejjen är den det är som du går i en affär. Det finns många köttbullar.. de ser likadana ut, men varje köttbulle har inget unikt id :(.. Om det är 3 köttbullar mer i ena disken än den andra så är det just de här 3 jag vill ha ut som svar ..

Permalänk
Medlem

Jag har svårt att sätta mig in i ditt problem, men du vet väl att du kan skapa subquerys for att filtrera ett resultat? Du kan också räkna antalet förekomster av dina "köttbullar" om du vill, kolla här; http://sweclockers.com/forum/showthread.php?s=&threadid=76875...

Det går att kombinera tekniker och skapa en hur avancerad query som helst, var inte rädd för att den blir lång och ser krånglig ut.

En länk till subquerying; http://www.roseindia.net/mysql/mysql5/writing-subqueries.shtm...

Permalänk
Medlem

ah. Jag ä rinte helt ny på det här. men just det här kan jag verkligen inte finna lösning på oavsett hur många joins och grejjer jag gör :/ om jag hade löst det med psuedo kod så hade det sett ut såhär. Kanske det hjälper att förklara hur jag skulle gjort.

Få ut alla värden ur tabell 1 som inte finns i tabell 2.

svar = tabell 1; foreach(rad1 in svar) { foreach(rad2 in tabell2) { if(rad1 == rad2) { svar.removerow(rad1); tabell2.removerow(rad2); break; } } }

så som sagt..
ta ut alla värden ur tabell 1..
Sen dra bort allt som finns i tabell 2.. (får ta bort det ur tabell 2 också så att man inte tar bort samma värde flera gånger). dvs. finns det 3 st av temp i tabell 1 och 2 i tabell två.. så ska bara två bort.
I värsta fall får jag lösa det på det här sättet.. Plocka ut båda tabellerna och lägga i listor sen köra det i kod. Därefter slänga in resultat i en tabell. Men nästlade for loopar är ju ingen höjdare. Speciellt inte när mina tabeller växer..
det handlar om ungefär 10 000 rader i båda tabellerna... vilket då blir maximalt 100 000 000 lopar... Ingen höjdare men jag ser ingen annan lösning.. Vet nite heller riktigt hur jag ska förklara..

det hade säkert gå att göra samma sak som SQL fråga. Men det måste ju verkligen finnas någonting som tar en tabell och bara drar bort en annan tabell... typ. Table1 exclude Table2.. eller nåt annat sånt :/

Permalänk
Medlem

men alltså. om du vill ha hjälp så måste du ge oss mer att gå på. Är det bara en kolumn eller flera, vad räknar du som lika rader, är det att en kolumn är lika eller ska alla kolumner vara lika? Jag skulle ev. kunna fixa en snyggare lösning åt dig, men då måste jag veta vilken databashanterare det är du använder och hur tabellerna ser ut.

Permalänk
Medlem

Det är egentligen massor med kolumner. Men för att göra det så lätt som möjligt så räcker det med att ni går på en kolumn. Jag kan nog utan större svårigheter ändra queryn så den passar mitt behov sen...

"Alla rader som finns i tabell 1 men inte i tabell 2".. Easy as that. Inget annat.
Observera dock att finns det 3 likadana rader i tabell 1 men bara 2 i tabell 2 så ska resultatet ge en av den här radtypen.

Jag förstår inte hur jag ska kunna förklara lättare än såhär.
Två tabeller. En kolumn vardera. och ett svar

Tabell1
aa
aa
aa
aa
ab
ac

Tabell2
aa
aa
ab
ao

Svar:
Som ni ser finns det fyra rader aa i tabell 1. och två i tabell två. 4-2 = 2. Dvs 2 rader med aa.
Och ab finns i tabell1. Men förekommer även i tabell 2. Så 1-1 = 0. dvs ingen rad med ab. Ac finns i tabell1 . och ingen i tabell2. Så.. 1-0 = 1. En rad då.

aa
aa
ac

Permalänk
Medlem

Det där finns det såvitt jag vet inte någon ensam query som kan lösa. det går dock med proceduellt språk, men eftersom du inte skriver vilken datbashanterare det är du använder kan jag inte hjälpa dig.

select c1 from t1 where c1 not in ( select c1 from t2 );

en sån fråga ger svaret ac bara (alltså aa och aa skulle inte finnas med) i ditt exempel ovanför. men det skulle kanske gå att konstruera bättre om man visste lite mer om tabellstrukturen. att köra 100 000 000 loopar är väldigt långt ifrån optimalt, och om man är tvingad att göra det så skulle det vara bättre att göra det direkt i databasen. Du kan inte konstruera om din tabellstruktur på något sätt så du slipper göra jämförelsen? Jag måste även tillägga att även om du skulle komma på något sätt att göra en enda query så måste de fält som jämförs även indexeras korrekt annars så kommer queryn att ta otroligt lång tid att köra ändå. Och index är inte heller så billigt alla gånger.

Permalänk
Medlem

Kan man inte göra något i denna stilen:

$query = "SELECT id FROM Tabell 2";
$result = mysql_query($query);
while($rad = mysql_fetch_array($result)){

$query2 = "SELECT id FROM Tabell 1";
$result2 = mysql_query($query);
$rad2 = mysql_fetch_array($result2);

$t2 = $rad['value'];
$t1 = $rad2['value'];

if($t1 != $t2){

$value = $t1;

}
}

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av thrawn
Det där finns det såvitt jag vet inte någon ensam query som kan lösa. det går dock med proceduellt språk, men eftersom du inte skriver vilken datbashanterare det är du använder kan jag inte hjälpa dig.

select c1 from t1 where c1 not in ( select c1 from t2 );

en sån fråga ger svaret ac bara (alltså aa och aa skulle inte finnas med) i ditt exempel ovanför. men det skulle kanske gå att konstruera bättre om man visste lite mer om tabellstrukturen. att köra 100 000 000 loopar är väldigt långt ifrån optimalt, och om man är tvingad att göra det så skulle det vara bättre att göra det direkt i databasen. Du kan inte konstruera om din tabellstruktur på något sätt så du slipper göra jämförelsen? Jag måste även tillägga att även om du skulle komma på något sätt att göra en enda query så måste de fält som jämförs även indexeras korrekt annars så kommer queryn att ta otroligt lång tid att köra ändå. Och index är inte heller så billigt alla gånger.

mySQL...

Nej det finns inget annat sätt att göra det på . Jag Gör en scan var halvtimme och får ut en massa objekt. Det jag ska göra är att kolla vilka objekt som har bortfallit sedan förra scannen. Dock har de inget unikt id för varje. Utan de har bara samma namn etc etc etc..
Men men..

Hoshibo, du är lite inne på det jag var innan. men där nästlar du det. men det kanske är nåt åt det hållet som får bli lösningen.

Permalänk
Medlem

Jag är inne på thrawns bana; om du behöver skapa en såhär avancerad query är det antagligen databasdesignen som är svag. Prova att strukturera om lite. En massa index är alltid en bra idé, de kan man göra mycket med. Timestamps använder du redan gissar jag?

Du skulle kunna exportera tabellstrukturen och klistra in koden här, det skulle göra det lättare att hjälpa dig. Om du använder phpMyAdmin till din MySQL-server är det bara att gå till rätt tabell och exportera strukturen (ej data).

Permalänk
Medlem

Hur kan en tabell bli lättare än en column? Är inte hemma nu men imorrn kan jag langa in hela tabellstrukturen. Fast det kommer inte förändra någonting.

Kan ge er sammanhanget så förstår ni.

Antar att de flesta känner till spelet world of warcraft. Vad jag gör är scannar av AH. Sparar allt i en tabell. Item Pris Säljare etc etc etc.
Det här gör jag en gång vart 30e min.
Nästa gång jag gör scannen.. Så har jag två tabeller som är identiska. Bortsett från att de items som är sålda sedan förra scannen saknas i tabell2. Det är de här jag vill ha ut. Om ni har nåt annat smart sätt att lösa det på så säg gärna till.

I själva verket är det inte en column. Men för att göra det lättare att förkla använde jag mig av enkolumnstabeller i exemplena.. Och hade man löst det på en sådan hade det varit lätt att applicera det på mina mer avancerade tabeller

PS, nej jag har inte tillgång till något itemID och det är egentligen där mitt problem har uppstått. Även om jag skulle tilldela items ett id vid varje scan så har jag inget sätt att veta om det är samma item nästa gång jag gör scannen.

edit: Tabell2 är egentligen bara en temporär tabell som jag skapar upp för att kunna göra den här jämförelsen direkt i SQL istället för att behöva skriva den i nästlade forloopar..

Permalänk
Medlem

well. mitt tips blir att skapa en procedur som tar hand om det hela och returnerar resultatet, det blir nog det optimala om du inte kan göra om databasstrukturen. Läs mer:

http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
http://se2.php.net/manual/en/mysqli.query.php#60473

Jag är inte så insatt i mysqls proceduella språk, måste läsa på lite själv, kan kanske hjälpa dig mer ikväll. men där har du lite att läsa iallafall...

ett till tips på vägen. om du bestämmer dig för att titta mer på det här alternativet så är det bästa att skapa en temp tabellen med resultaten för att sen returnera det. det viktiga då är att bara spara tabellen i minnet (nyckelord memory) i mysql.

Exempel:
http://forums.mysql.com/read.php?98,203671,203838#msg-203838

EDIT: efter att ha läst ditt sista inlägg så är jag övertygad om att det här är det bästa sättet. Då behöver du inte ens in i php mer än att för att göra den inledande uppsamlingen av data. Då gör du helt enkelt bara uppsamlingen sen kallar du på proceduren i mysql som gör jämförelsen och lagrar det i en passande tabell. För jag antar att du lagrar de items som blivit sålda? Eller skriver du ut det på en sida bara?

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av thrawn
well. mitt tips blir att skapa en procedur som tar hand om det hela och returnerar resultatet, det blir nog det optimala om du inte kan göra om databasstrukturen. Läs mer:

http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
http://se2.php.net/manual/en/mysqli.query.php#60473

Jag är inte så insatt i mysqls proceduella språk, måste läsa på lite själv, kan kanske hjälpa dig mer ikväll. men där har du lite att läsa iallafall...

ett till tips på vägen. om du bestämmer dig för att titta mer på det här alternativet så är det bästa att skapa en temp tabellen med resultaten för att sen returnera det. det viktiga då är att bara spara tabellen i minnet (nyckelord memory) i mysql.

Exempel:
http://forums.mysql.com/read.php?98,203671,203838#msg-203838

tack, alla tips är välkomna.. är som sagt helt fast.. Nu har jag iaf någonting att jobba med. : )

Permalänk
Medlem

Jag förstår inte riktigt vad du vill ha, men hur skulle det här fungera:

1) Scanna, lägg in resultatet i tabell A.
2) Kopiera allt i tabell A till tabell B.
3) Scanna igen och ta bort poster från tabell B, lägg in poster i tabell A.

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607

Permalänk
Medlem

Det är roligt med folken som lägger upp någon lösning i ASP eller PHP och sedan totalt ignoreras för att de missat att det ska göras i SQL och att databaser används till mer än LunarStorm.

Visa signatur

Into the Web Browser for iPhone, http://www.intothewebbrowser.com/