SQL: nybörjarfråga om JOIN och ORDER BY

Tråden skapades och har fått 14 svar. Det senaste inlägget skrevs .
1
  • Medlem
  • Stockholm
  • 2005-04-07 11:06

Har tre tabeller som jag ska hämta totalt 10st poster ifrån sorterat efter deras skapelsedatum.

Att endast välja 10 st poster görs enkelt med LIMIT 10, men resten är jag osäker på. Behöver veta om det är en nyhet, konferens eller händelse som hämtas också för de ska ha olika css-klasser.

Tack på förhand
V.h.
Ivar

Events

mysql> describe events;
+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| id            | int(6)      |      | PRI | NULL    | auto_increment |
| header        | varchar(50) |      |     |         |                |
| intro         | text        |      |     |         |                |
| body          | text        |      |     |         |                |
| location      | varchar(60) |      |     |         |                |
| date_created  | int(11)     |      |     | 0       |                |
| date_modified | int(11)     |      |     | 0       |                |
| date_event    | int(11)     |      |     | 0       |                |
+---------------+-------------+------+-----+---------+----------------+

News

mysql> describe news;  
+---------------+---------------+------+-----+---------+----------------+
| Field         | Type          | Null | Key | Default | Extra          |
+---------------+---------------+------+-----+---------+----------------+
| id            | int(11)       |      | PRI | NULL    | auto_increment |
| date_created  | int(11)       |      |     | 0       |                |
| date_modified | int(11)       |      |     | 0       |                |
| date_event    | int(11)       |      |     | 0       |                |
| header        | varchar(60)   |      |     |         |                |
| intro         | text          |      |     |         |                |
| body          | text          |      |     |         |                |
| in_calendar   | enum('Y','N') |      |     | N       |                |
+---------------+---------------+------+-----+---------+----------------+

Conferences

mysql> describe conferences;
+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| id            | int(4)      |      | PRI | NULL    | auto_increment |
| date_created  | int(11)     |      |     | 0       |                |
| date_modified | int(11)     |      |     | 0       |                |
| date_event    | int(11)     |      |     | 0       |                |
| header        | varchar(60) |      |     |         |                |
| intro         | text        |      |     |         |                |
| body          | text        |      |     |         |                |
| location      | varchar(60) |      |     |         |                |
+---------------+-------------+------+-----+---------+----------------+
Senast redigerat 2005-04-07 11:17
  • Medlem
  • Höganäs
  • 2005-04-07 11:19

Kort fråga:
Varför har du snarlik information i tre olika tabeller istället för en?

Ursprungligen av Micke F:

Kort fråga:
Varför har du snarlik information i tre olika tabeller istället för en?

Mycket för att gära det lättare att hantera all info.
Sedan att namen är snarlika för posterna säger inte att infon är likartad.

  • Medlem
  • Höganäs
  • 2005-04-07 11:24
Ursprungligen av Mattias Hedman:

Mycket för att gära det lättare att hantera all info.
Sedan att namen är snarlika för posterna säger inte att infon är likartad.

Ok. Sant.

På slutet av SQL satsen kan du skriva:
ORDER BY date_created DESC
Tror det är DESC aller ASC lär mig aldrig vilket som är vilket...

Men gör du en full join mellan alla tre tabeller?
Lite luddigt tycker jag.

Men varför använder du inte timestamp för datum och tider?

  • Medlem
  • Stockholm
  • 2005-04-07 23:17

Hmm.. Måste jag hämta 10st poster från varje tabell och lägga i en array där jag sen sorterar igen på date_created och först därefter hämtar de 10 första/sista posterna?

Mattias, Jag diggar unix timestamp mer än mysql timestamp

Senast redigerat 2005-04-07 23:34
Ursprungligen av ivar:

Mattias, Jag diggar unix timestamp mer än mysql timestamp

Fast poängen med mysqls timestamp är att den första timestampkolumnen i en tabell (man kan ha flera) uppdaterar sig själv automatiskt när raden i databasen uppdateras. Och att du kan definiera den till 8 tkn, och få ett datum enl ååååmmdd, för att sedan definiera om den till, säg, 10 tkn, och output blir åååå-mm-dd, och om du ytterligare definierar om den kan du få ut exempelvis åååå-mm-dd hh:mm.

Detta oberoende av hur många tecken den var definierad till när du lade in data; mysql sparar hela unixtimestampet, och visar så mkt av det som den kan efter den längd du definierar den till.

  • Medlem
  • Stockholm
  • 2005-04-08 19:14
Ursprungligen av scooterbabe:

Fast poängen med mysqls timestamp är att den första timestampkolumnen i en tabell (man kan ha flera) uppdaterar sig själv automatiskt när raden i databasen uppdateras.

Jag vill helst kontrollera vad som händer med mina fält själv. Jag vet att MySQL har gjort det så fiffigt att det första timestamp-fältet man har i sin lista uppdateras automagiskt när man ändrar vad som helst hos raden. Men jag skriver hellre in det i min kod.

Ursprungligen av scooterbabe:

Och att du kan definiera den till 8 tkn, och få ett datum enl ååååmmdd, för att sedan definiera om den till, säg, 10 tkn, och output blir åååå-mm-dd, och om du ytterligare definierar om den kan du få ut exempelvis åååå-mm-dd hh:mm.

Detta oberoende av hur många tecken den var definierad till när du lade in data; mysql sparar hela unixtimestampet, och visar så mkt av det som den kan efter den längd du definierar den till.

Ja precis, MySQL sparar ändå all information.. det känns som man bara väljer en default-formatering av sitt timestamp. Jag sparar hellre datumet i "rå-format" (öhh. precis som mysql) och skriver ut det som jag vill ha det på mina olika sidor, m.h.a. PHP och strftime (månader på svenska m.m.).
Går ju såklart att göra vilket som men jag förderar unixtimestamps.

Det här med unionerna ...

$sql ="
   SELECT *
   FROM (SELECT *, 1 as temp from tabel1) union (select *, 2 as temp from tabel2)  union (select *, 3 as temp from tabel3)
   ORDER BY temp DESC
   LIMIT 10
   ";

Jag har en SQL-bibel så jag ska sätta mig och slå lite i den... men kan inte någon försöka skriva om den där frågan så den fungerar för mina tabeller jag definierat ovan?

Jag fattar intet riktigt vad 1 som kolumnnamn innebär...

SELECT *, 1 AS temp

Tack för all hjälp iaf !

v.h.
Ivar

Citat:

Jag fattar intet riktigt vad 1 som kolumnnamn innebär...

SELECT *, 1 AS temp

Jag antar att det är för att du i unionen skall se vilken tabell som är ursprungstabellen.

1'an skall väl då lägga in en kolumn som heter temp med bara ettor i.

Ursprungligen av hanha014:

Jag antar att det är för att du i unionen skall se vilken tabell som är ursprungstabellen.

1'an skall väl då lägga in en kolumn som heter temp med bara ettor i.

Det stämmer.

Eller som jag skrev i ursprungsinlägget:

Citat:

Koden ovan gör, förutom att den merge-ar ihop tabellerna, även att en ny kolumn skapas temporärt, vilkens innehåll blir "1" om raden i fråga kommer från tabell1, 2 om den kommer från tabell2 etc.

Den som läser skola finna...

  • Medlem
  • Nacka
  • 2005-04-07 23:49

Har jag förstått det rätt att du vill ha en kombinerad lista med nyheter, händelser och konferenser?
Såvitt jag kan komma på så finns det nog inget vettigt sätt att göra det med en enda select-sats. Antingen får du gör en enda tabell med allt innehåll i stil med

+---------------+---------------+------+-----+---------+----------------+
| Field         | Type          | Null | Key | Default | Extra          |
+---------------+---------------+------+-----+---------+----------------+
| id            | int(6)        |      | PRI | NULL    | auto_increment |
| header        | varchar(50)   |      |     |         |                |
| intro         | text          |      |     |         |                |
| body          | text          |      |     |         |                |
| location      | varchar(60)   |      |     |         |                |
| date_created  | int(11)       |      |     | 0       |                |
| date_modified | int(11)       |      |     | 0       |                |
| date_event    | int(11)       |      |     | 0       |                |
| in_calendar   | enum('Y','N') |      |     | N       |                |
| type          | char(1)       |      |     | N       |                |
+---------------+---------------+------+-----+---------+----------------+

där type bestämmer om det är en händelse, nyhet eller en konferens.
och sedan bara köra en enkel selectsats i stil med
SELECT * FROM tabel-namn ORDER BY date_created DESC;

  • Medlem
  • Stockholm
  • 2005-04-07 23:53

Jo då blir det ju busenkelt. Ska vara lite mer utmaning
Men det verkar svårt att joina 3 tabeller och sortera som jag ville.... får bli "Hämta 10 från varje"-varianten... tack iaf!

Ursprungligen av ivar:

Jo då blir det ju busenkelt. Ska vara lite mer utmaning

Hm, låter kanske lite väl masochistiskt, men låt gå Active Record (databaskomponenten i Rails) använder ungefär den principen när man har flera klasser som delar en tabell, lägger man bara till en kolumn "type" fixas kopplingen till rätt klass automagiskt. Tycker det fungerar väldigt bra faktiskt.

Ett alternativ, annars, för den som kör postgresql är att skapa tabeller med arv, det är ungefär samma princip som arv i OO-programmering. Men den finessen är rätt märklig och dessutom lite defekt, så jag brukar använda type-kolumner i stället.

Citat:

Men det verkar svårt att joina 3 tabeller och sortera som jag ville.... får bli "Hämta 10 från varje"-varianten... tack iaf!

Annars kan du göra som scooterbabe säger - d.v.s. köra en subselect där du slår ihop datat från alla tabeller med union, sedan sorterar du det resultatet som om det kom från en och samma tabell. Snyggast är såklart om du kan skapa en vy i stället, men då vill det till att du kör antingen MySQL 5 eller byter till någon DB som rentav har vettigt stöd för SQL-standarden (postgresql, firebird, sqlite, m.fl.).

Om jag förstår rätt vill du helt enkelt "merge"-a ihop tabellerna, för att sedan sortera dem på datum med möjlighet att veta från vilken tabell posten ursprungligen kom från?

Är det så kan du väl göra tre stycken UNION, där du i princip skriver

(SELECT *, 1 as temp from tabel1) union (select *, 2 as temp from tabel2)  union (select *, 3 as temp from tabel3) order by temp desc limit 10;

Koden ovan gör, förutom att den merge-ar ihop tabellerna, även att en ny kolumn skapas temporärt, vilkens innehåll blir "1" om raden i fråga kommer från tabell1, 2 om den kommer från tabell2 etc.

Att tänka på när du gör UNIONS är att subselect-arna måste ha samma antal kolumner av samma typ, d v s har du kolumnerna kolumn1 och kolumn2 i tabell1, men bara kolumn2 i tabell2, måste du skapa en temporär kolumn "on the fly" när du kör din query, som i exemplet ovan och i detta exempel enligt (select "foo" as kolumn1, kolumn2 from tabell2).

Har du sedan kolumner med samma namn men av olika typ får du se till att omdefiniera dem också "on the fly", något jag inte kommer ihåg hur det ser ut i mySQL, men i postgresQL gör man det genom att skriva "SELECT ..., heltalskolumntilltext::text, nästakolumn, ... from blaha".

Hoppas det här hjälper dig,

/.scooter

  • Medlem
  • Stockholm
  • 2005-04-08 23:10

Ahaaaa, förstås!
Tackar!

1
Bevaka tråden