---
title: "Hitta datum som _inte_ finns i tabell"
type: "forum-thread"
url: "https://www.webforum.nu/amne/databaser-sql/182062-hitta-datum-som-inte-finns-i-tabell/page2"
topic: "Databaser & SQL"
topic_url: "https://www.webforum.nu/amne/databaser-sql"
author: "MickeA.com"
published: "2010-01-18T14:13:24.000Z"
updated: "2010-04-20T11:38:02.000Z"
replies: 36
views: 2079
page: 2
pages: 2
language: "sv-SE"
site: "webForum — webforum.nu"
rights: "Upphovsrätten till varje inlägg tillhör dess författare."
attribution: "Citera som: webForum, https://www.webforum.nu/amne/databaser-sql/182062-hitta-datum-som-inte-finns-i-tabell"
---

# Hitta datum som _inte_ finns i tabell

_Sida 2 av 2._

## #21 — nitro2k01, 2010-01-21T08:37Z

Micke, av smutsig nyfikenhet, hur lång tid tar min fråga?

Permalänk: https://www.webforum.nu/p/2223650

## #22 — MickeA.com, 2010-01-21T10:48Z

> **[nitro2k01 skrev:](https://www.webforum.nu/p/1495269)**
>
> Micke, av smutsig nyfikenhet, hur lång tid tar min fråga?

**0\.16 sek**, men den ger "Empty set" av någon anledning!? Jag har bytt ut dina fält/tabellnamn mot mina motsvarande.

Permalänk: https://www.webforum.nu/p/2223660

## #23 — nitro2k01, 2010-01-21T11:00Z

Har du petat in vettiga datum på alla tre ställen? Säker på att intervallet är så stort att det innefattar minst en existerande post? (Se buggbeskrivningen)

Permalänk: https://www.webforum.nu/p/2223662

## #24 — MickeA.com, 2010-01-21T15:15Z

Det här kör jag:

```
SELECT
    DATE_ADD(g1.datetime, INTERVAL 1 DAY) AS vacancystart,
    DATEDIFF(COALESCE(MIN(g2.datetime),'2010-01-19'),g1.datetime)-1 AS vacancylength
FROM `stats` g1
LEFT JOIN `stats` g2 ON g2.datetime > g1.datetime 
WHERE g1.datetime < '2010-01-19' AND g1.datetime > '2009-01-01'
GROUP BY g1.datetime
HAVING vacancylength>0;
```

Nu har frågan stått och tuggat i **7750 sekunder**, så jag stänger av den nu... :)

Kör jag min feeta procedure på samma datum får jag:

```
+------------+-------------------+
| tmpDate    | count(joiner.dte) |
+------------+-------------------+
| 2009-01-01 |                 0 |
| 2009-01-02 |                 0 |
| 2009-01-03 |                 0 |
| 2009-01-04 |                 0 |
| 2009-01-05 |                 0 |
| 2009-01-06 |                 0 |
| 2009-01-07 |                 0 |
| 2009-01-08 |                 0 |
| 2009-01-09 |                 0 |
| 2009-01-10 |                 0 |
| 2009-01-11 |                 0 |
| 2009-01-12 |                 0 |
| 2009-01-13 |                 0 |
| 2009-01-14 |                 0 |
| 2009-01-15 |                 0 |
| 2009-01-16 |                 0 |
| 2009-01-17 |                 0 |
| 2009-01-18 |                 0 |
| 2009-01-19 |                 0 |
| 2009-01-20 |                 0 |
| 2009-01-21 |                 0 |
| 2009-01-22 |                 0 |
| 2009-01-23 |                 0 |
| 2009-01-24 |                 0 |
| 2009-01-25 |                 0 |
| 2009-01-26 |                 0 |
| 2009-01-27 |                 0 |
| 2009-01-28 |                 0 |
| 2009-01-29 |                 0 |
| 2009-01-30 |                 0 |
| 2009-01-31 |                 0 |
| 2009-02-01 |                 0 |
| 2009-02-02 |                 0 |
| 2009-02-03 |                 0 |
| 2009-02-04 |                 0 |
| 2009-02-05 |                 0 |
| 2009-02-06 |                 0 |
| 2009-02-07 |                 0 |
| 2009-02-08 |                 0 |
| 2009-02-09 |                 0 |
| 2009-02-10 |                 0 |
| 2009-02-11 |                 0 |
| 2009-02-12 |                 0 |
| 2009-02-13 |                 0 |
| 2009-02-14 |                 0 |
| 2009-02-15 |                 0 |
| 2009-02-16 |                 0 |
| 2009-02-17 |                 0 |
| 2009-02-18 |                 0 |
| 2010-01-13 |                 0 |
| 2010-01-14 |                 0 |
| 2010-01-15 |                 0 |
| 2010-01-16 |                 0 |
| 2010-01-17 |                 0 |
+------------+-------------------+
54 rows in set (1.80 sec)

Query OK, 0 rows affected, 1 warning (2.17 sec)
```

Permalänk: https://www.webforum.nu/p/2223677

## #25 — nitro2k01, 2010-01-21T16:58Z

Nu ser jag probsemet med min fråga... joinen joinar en massa rader som den bara kastar bort (tror jag) Återkommer med en ny fråga snart.
Men alldeles oavsett hur du gör så har du allt att vinna på att sätta på indexering på datumfältet!

Permalänk: https://www.webforum.nu/p/2223686

## #26 — MickeA.com, 2010-01-21T17:01Z

> **[nitro2k01 skrev:](https://www.webforum.nu/p/1495315)**
>
> Men alldeles oavsett hur du gör så har du allt att vinna på att sätta på indexering på datumfältet!

Vilken typ av index? Jag lade till en kolumn som primärnyckel med AI, men det kanske inte gör någon skillnad?

Permalänk: https://www.webforum.nu/p/2223688

## #27 — nitro2k01, 2010-01-21T17:07Z

Vanligt index. (För datumkolumnen) Möjligen unique om det är ställt bortom allt tvivel att det inte existerar dublettdatum. 
Att ha en annan nolumn som primärnyckel gör inte sökningar baserat på datum snabbare. Genom att indexera datumkolumnen kan DB-motorn göra saker som att leta upp nästa datum snabbare. (Vilket den behöver göra internt.)

Permalänk: https://www.webforum.nu/p/2223690

## #28 — MickeA.com, 2010-01-23T19:40Z

Tabellen krympte med \~1Mb efter att jag satt datetime som index. Coolt.

Permalänk: https://www.webforum.nu/p/2223875

## #29 — nitro2k01, 2010-01-23T22:00Z

Så, pröva både min fråga och proceduren nu. :)

Permalänk: https://www.webforum.nu/p/2223894

## #30 — MickeA.com, 2010-04-20T10:20Z

Nu tänkte jag modifera den här proceduren något, jag vill nämligen kunna ange tabellnamn som indata till den, tillsammas med två datum.

Det funkar så att jag har flera tabeller med statistik och fältet jag ska jämföra emot heter "datetime" i alla tabeller, så det är endast tabellnamnet jag behöver kunna "ändra".

Såhär ser den fungerande funktionen ut:

```
DELIMITER //
DROP PROCEDURE IF EXISTS checkDateAvailability//
CREATE PROCEDURE checkDateAvailability(d1 date, d2 date)
BEGIN
   DECLARE currentDate DATETIME;

   DROP TEMPORARY TABLE IF EXISTS foo;
   CREATE TEMPORARY TABLE foo(tmpDate DATE NOT NULL);

   SET currentDate = d1;
   WHILE currentDate <= d2 DO
      INSERT INTO foo(tmpDate) VALUES(currentDate);
      SET currentDate = DATE_ADD(currentDate, INTERVAL 1 DAY);
   END WHILE;

   SELECT
      foo.tmpDate, count(joiner.dte)
   FROM
      foo
      LEFT JOIN
         (SELECT
             DISTINCT(my_table.datetime) as dte
          FROM
             my_table
         ) AS joiner
         ON foo.tmpDate = joiner.dte
   GROUP BY
      foo.tmpDate
   HAVING
      COUNT(joiner.dte) = 0
   ORDER BY
      foo.tmpDate ASC;

   DROP TEMPORARY TABLE foo;
END//
DELIMITER ;
```

Är lite osäker på datatypen jag ska skicka in, antar att det ska vara "STR" eller något sånt.

Förslag?

Permalänk: https://www.webforum.nu/p/2233379

## #31 — SPiN, 2010-04-20T10:29Z

Det går, men blir inte snyggt;

```
DELIMITER //
DROP PROCEDURE IF EXISTS checkDateAvailability//
CREATE PROCEDURE checkDateAvailability(tblname varchar(30), d1 date, d2 date)
BEGIN
   DECLARE currentDate DATETIME;

   DROP TEMPORARY TABLE IF EXISTS foo;
   CREATE TEMPORARY TABLE foo(tmpDate DATE NOT NULL);

   SET currentDate = d1;
   WHILE currentDate <= d2 DO
      INSERT INTO foo(tmpDate) VALUES(currentDate);
      SET currentDate = DATE_ADD(currentDate, INTERVAL 1 DAY);
   END WHILE;

   SET @prep = CONCAT('SELECT foo.tmpDate, count(joiner.dte) FROM foo LEFT JOIN (SELECT DISTINCT(', tblname, '.datetime) as dte FROM ', tblname, ') AS joiner ON foo.tmpDate = joiner.dte GROUP BY foo.tmpDate HAVING COUNT(joiner.dte) = 0 ORDER BY foo.tmpDate ASC;');
    PREPARE stmt FROM @prep;
    EXECUTE stmt;
    DEALLOCATE PREPARE @prep;

   DROP TEMPORARY TABLE foo;
END//
DELIMITER ;
```

Lite osäker dock, men det bör fungera. Notera att du måste skriva ihop frågan till en sträng.

Permalänk: https://www.webforum.nu/p/2233381

## #32 — MickeA.com, 2010-04-20T10:32Z

Jag får:

```
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near '@prep
;
```

Är det bättre att ha fyra olika procedurer, eller är det något annat som gör att det inte "är snyggt"?

Permalänk: https://www.webforum.nu/p/2233382

## #33 — MickeA.com, 2010-04-20T10:42Z

Kan tillägga att jag även vill kunna få ut alla datum i ett recordset, måste jag använda mig av IN/OUT då? Verkar som om man (med PHP) får köra två separata anrop, t.ex.:

```php
mysql_query("CALL check...");
$res = mysql_query("SELECT @MIN_OUT_VAR");
```

Hur hänger det ihop?

Permalänk: https://www.webforum.nu/p/2233383

## #34 — MickeA.com, 2010-04-20T11:08Z

Har läst på lite nu och det verkar som om det inte går att få tillbaka ett recordset till PHP på ett smidigt sätt. Man kan däremot använda **mysqli** och följande kod:

```php
$db = mysqli_connect($db_host, $db_user, $db_passwd);
$db->select_db($db_name);
$db->query("SET NAMES utf8") or die(mysqli_error());
$db->query("SET CHARACTER SET utf8") or die(mysqli_error());
$db->multi_query("CALL checkDateAvailability('2009-01-01', '2010-03-01')");

while($result = $db->store_result()){
	while($row = $result->fetch_row()){
		echo $row[0] . "<br />";
	}
	$result->close();
	$db->next_result();
}
```

Ger exakt det resultat jag vill ha:

```
2009-01-01
2009-01-02
2009-01-03
2009-01-04
2009-01-05
2009-01-06
2009-01-07
...
2009-02-16
2009-02-17
2009-02-18
```

Då återstår bara det här med tabellnamnet...

Permalänk: https://www.webforum.nu/p/2233386

## #35 — SPiN, 2010-04-20T11:23Z

Hm, @ kanske är överflödig?

```
...
   SET prep = CONCAT('SELECT foo.tmpDate, count(joiner.dte) FROM foo LEFT JOIN (SELECT DISTINCT(', tblname, '.datetime) as dte FROM ', tblname, ') AS joiner ON foo.tmpDate = joiner.dte GROUP BY foo.tmpDate HAVING COUNT(joiner.dte) = 0 ORDER BY foo.tmpDate ASC;');
    PREPARE stmt FROM prep;
    EXECUTE stmt;
    DEALLOCATE PREPARE prep;
...
```

Permalänk: https://www.webforum.nu/p/2233388

## #36 — MickeA.com, 2010-04-20T11:32Z

Då får jag istället: 

```
ERROR 1193 (HY000): Unknown system variable 'prep'
```

Permalänk: https://www.webforum.nu/p/2233389

## #37 — SPiN, 2010-04-20T11:38Z

Hm, @ är alltså nödvändigt som jag trodde.

Följande är från MySQL.com, och gäller från version 5.0 (då stored procedures introducerades).

```
delimiter //
DROP PROCEDURE IF EXISTS colavg//
CREATE PROCEDURE colavg(IN tbl CHAR(64), IN col CHAR(64))
READS SQL DATA
COMMENT 'Selects the average of column col in table tbl'
BEGIN
SET @s = CONCAT('SELECT AVG(' , col , ') FROM ' , tbl);
PREPARE stmt FROM @s;
EXECUTE stmt;
END;
//
delimiter ;
```

<http://dev.mysql.com/tech-resources/articles/mysql-storedproc.html>

Märkligt om det inte fungerar? Har inte ork att försöka själv tyvärr...

Permalänk: https://www.webforum.nu/p/2233390

---

Tråden på webben: https://www.webforum.nu/amne/databaser-sql/182062-hitta-datum-som-inte-finns-i-tabell/page2  
Föregående sida: https://www.webforum.nu/amne/databaser-sql/182062-hitta-datum-som-inte-finns-i-tabell.md
