WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   JOIN på date (https://www.wn.se/forum/showthread.php?t=5374)

Robert 2005-01-07 23:17

Hmmm, har kliat skallen ett tag nu hur man gör en join på två datetime fält i MSSQL (Transact SQL). Problemet är givetvis tidsdelen av datumet som skiljer sig åt. Går det att klippa bort tiden när man gör denna join?

Kod:

Tabell1:

datum * * * * * * * * * * * * * * * * * * text1
--------------------------------------------
2005-01-01 10:02:34 * * * * * * bla
2005-01-02 00:00:12 * * * * * * blabla * ** * <---join blir fel pga tiden
2005-01-06 12:33:20 * * * * * * blablabla



Tabell2:

datum * * * * * * * * * * * * * * * * * * text2
--------------------------------------------
2004-12-01 10:02:34 * * * * * * hehehe
2005-01-02 04:32:32 * * * * * * hehe * * * <---join blir fel pga tiden
2005-01-03 10:02:34 * * * * * * he


vill ha det till:

datum * * * * * * * * * * * * * * * * * * text1 * * * * * *text2
-------------------------------------------------------------------
2004-12-01        * * * * * * NULL * * * * * * hehehe
2005-01-01        * * * * * * bla * * * * * * * * NULL
2005-01-02        * * * * * * blabla * * * * * *hehe
2005-01-03        * * * * * * NULL * * * * * * *he
2005-01-06        * * * * * * blablabla * * * *NULL


Lindahl 2005-01-07 23:41

Datum lagras oftast i form av flyttal där dagen bestäms av heltalsdelen och tiden av decimal-delen. Mig veterligen finns det ingen funktion för att trunkera datum till att enbart gå på heltalet, men en alternativ lösning som du kanske kan testa är ju att lägga in att den jämför om datumet ligger inom intervallet kl 00.00:00-23.59:59 under ett visst dygn. Om detta går att tillämpa i just en join-sats är jag dock osäker på.

Robert 2005-01-08 00:10

Jag har testat att efter min select göra om datumet till en char med endast 10 tecken (går på andra sätt också), exemeplvis:


Kod:


SELECT
  T1.*,
  T2.*,
  convert(char(10), T1.datum, 102) as datum1,
  convert(char(10), T2.datum, 102) as datum2
  FROM Tabell1 T1
  JOIN Tabell2 T2 ON datum1 = datum2
  WHERE
    ...etc...etc


men det fungerar ju inte...

eg0master 2005-01-08 00:11

om du istället för:
tabell1.datum resp tabell2.datum
skriver:
covert(char(10),tabell1.datum,120) resp covert(char(10),tabell2.datum,120)

så kommer du bara jämföra datum som är identiska.

Fast om det är så att datat pga buggig inläggning (dvs den lägger in med tid trots att det är bara datumet som är intressant) så bör du kika på inläggningen istället så du slipper converta i selecten.

De poster som redan finns kan ju i så fall enkelt uppdateras med en convert.

eg0master 2005-01-08 00:14

Ser att du kom på lösningen själv...

Det jag tror du gör fel nu är att du inte gör en outer join.
Det "som inte funkar" är att dina rader med "null" (för att datumen finns i en tabell men inte den andra) saknas. korrekt?

Robert 2005-01-08 13:14

Nja, min lösning fungerar ju inte riktigt.

Jag kan inte joina på datum1 och datum2 då får jag ett fel: invalid columnname 'datum1' (respektive 'datum2')

Och det ska vara JOIN, dvs om jag har förstått JOIN'ar rätt. Jag har liksom flera tabeller med loggdata som ska paketeras ihop på "bredden" dvs data ifrån flera olika loggar ska skrivas in i olika fält på samma rad i recordset'et. En inner/outer/left join exkluderar ju åt endera hållet, här ska det vara villkorslöst. Ingen logg bestämmer om en annan logg ska finnas med mao.

Och jag måste ha med tid i fältet för dessa tabeller används i andra sammanhang där tidsstämpel är viktig...

eg0master 2005-01-08 14:46

Funkar inte?
Kod:

SELECT
  T1.*,
  T2.*
  FROM Tabell1 T1
  JOIN Tabell2 T2 ON convert(char(10), T1.datum, 102) = convert(char(10), T2.datum, 102)
  WHERE
  ...etc...etc

och alltså en join som du gör kommer begränsa resultatet till bara de rader där T1.datum=T2.datum existerar.

left/outer joins är ett måste om du vill ha "null där värde saknas", således måste du låte en tabell styra över den andra.

Om du verkligen inte har någon tabell som styr så får du nog köra en union enligt principen: Välj alla som har matchning UNION alla som bara finns i T1 UNION alla som bara finns i T2.

Kod:

select T1.*, T2.* FROM T1, T2 WHERE convert(char(10), T1.datum, 102) = convert(char(10), T2.datum, 102)
UNION
select T1.*, T2.* FROM T1, T2 WHERE convert(char(10), T1.datum, 102) =* convert(char(10), T2.datum, 102) AND convert(char(10), T2.datum, 102) not in (select convert(char(10), T2.datum, 102) FROM T1, T2 WHERE convert(char(10), T1.datum, 102) = convert(char(10), T2.datum, 102))
UNION
select T1.*, T2.* FROM T1, T2 WHERE convert(char(10), T1.datum, 102) *= convert(char(10), T2.datum, 102) AND convert(char(10), T1.datum, 102) not in (select convert(char(10), T1.datum, 102) FROM T1, T2 WHERE convert(char(10), T1.datum, 102) = convert(char(10), T2.datum, 102))

Något i den stilen borde göra jobbet, men frågan är om det inte är enklare (nu när du saknar "styrtabell") plocka ut resultat för resultat loopa igenom datumen manuellt och skapa den output du vill ha. Ett alternativ till UNION är ju så klart att lägga resultetaten i en temptabell och bygga upp det färdiga resultetatet den vägen, lämpligen i en SP.

Robert 2005-01-09 21:00

Tack, ego.

Det blev en variant på dina UNION's som löste det. Kan inte mixtra så mycket med recordset'et pga den lösning jag har valt (jag skjuter in resultatet rakt in i en kontroll (asp.net vettu...)

Jag får bjuda på en virtuell öl som tack för hjälpen. B)

eg0master 2005-01-09 21:14

Citat:

Originally posted by Robert@Jan 9 2005, 22:00
Tack, ego.

Det blev en variant på dina UNION's som löste det. Kan inte mixtra så mycket med recordset'et pga den lösning jag har valt (jag skjuter in resultatet rakt in i en kontroll (asp.net vettu...)

Jag får bjuda på en virtuell öl som tack för hjälpen. B)

jag menade inte att du skulle mixtra med datasetet utan att du i en SP (Stored Procedure) skulle skapa en temptabell med ditt önskade utseende och sedan fylla temptabellen bit för bit (istf en gigantisk union) och sedan göra select * från din temptabell.


Alla tider är GMT +2. Klockan är nu 14:18.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson