---
title: "MySQL: Skydd mot dubbelbokning, större än och mindre än?"
type: "forum-thread"
url: "https://www.webforum.nu/amne/databaser-sql/187610-mysql-skydd-mot-dubbelbokning-större-än-och-mindre-än"
topic: "Databaser & SQL"
topic_url: "https://www.webforum.nu/amne/databaser-sql"
author: "MickeA.com"
published: "2011-08-16T15:26:07.000Z"
updated: "2011-08-29T03:37:32.000Z"
replies: 11
views: 2195
page: 1
pages: 1
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/187610-mysql-skydd-mot-dubbelbokning-större-än-och-mindre-än"
---

# MySQL: Skydd mot dubbelbokning, större än och mindre än?

## #1 — MickeA.com, 2011-08-16T15:26Z

Hej,

Har ett system där man bokar in sig till aktiviteter. Varje aktivitet har ett start och ett slutdatum. Nu behöver jag blockera vid bokning så man aldrig ska kunna boka in sig till två aktiviteter där start -och slutdatum krockar på något sätt.

Hittills har jag kört en BETWEEN sats och kollat om tidigare bokad plats \_slutdatum\_ ligger mellan ny aktivitets start -och slutdatum, men har visat sig inte vara 100%-igt.

Så, hur ska jag göra istället? Tänker mig något liknande det här:

```
...
WHERE REDAN_BOKAD_AKT_START >= NY_AKT_START OCH REDAN_BOKAD_AKT_SLUT <= NY_AKT_SLUT
```

Blir det rätt? Det ska alltså fungera så att om jag redan är inbokad på en aktivitet som pågår 1'a - 10'e Augusti, så ska 1-10 Aug vara "låsta" datum, jag ska endast kunna boka in mig på en grupp som inte ligger inom samma period som en redan bokad aktivitet.

Tacksam för förslag!

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

## #2 — MickeA.com, 2011-08-22T01:14Z

Jag får inte till det här alls... Vid en sökning på wF hittade jag den här tråden:
<http://www.webforum.nu/showthread.php?s=&postid=675965#post675965>

Har nu provat med frågan där men det fungerar inte i mitt fall. Förutom datumen har jag ett gäng andra parametrar. T.e.x. så tillhör varje aktivitet en kategori (section_id) och den ska bara kolla på samma användare som försöker boka igen.

Såhär ser det ut:

```
SELECT 
a.`not_id`, 
b.`group_id` 
FROM `school_notifies` a 
INNER JOIN `school_group` b 
ON a.`not_group_id` = b.`group_id` 
	INNER JOIN `school_level` c 
	ON b.`group_parent` = c.`level_id` 
	  INNER JOIN `school_type` d 
	  ON c.`level_parent` = d.`type_id` 
		INNER JOIN `school_section` e 
		ON d.`type_parent` = e.`section_id` 
WHERE a.not_user_id = 1 
AND a.`not_type` = 1 
AND a.`not_confirmed` IS NOT NULL 
AND e.`section_id` = 3 
AND <START> BETWEEN b.`group_start` AND b.`group_end` 
OR <SLUT> BETWEEN b.`group_start` AND b.`group_end`
```

Det fungerar \_nästan\_. Har jag redan en bokning som sträcker sig från *2011-09-01* till *2011-10-31* så får jag fortfarande boka *2011-08-01* till *2011-12-01*.

Det ska ju inte fungera, eftersom den perioden sträcker sig över min tidigare bokning. 

Hur ska jag lösa det här?

Tack!

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

## #3 — @nders, 2011-08-22T05:10Z

Så som du har skrivit frågan räcker det med att villkoret *\<SLUT\> BETWEEN b.\`group_start\` AND b.\`group_end\`* stämmer för att du ska få träff. Är det det du vill? Gruppera annars med parenteser. Kan det möjligen vara så att du vill att alla de första villkoren skall uppfyllas, samt (minst) ett av de två sista?

```
WHERE a.not_user_id = 1 
AND a.`not_type` = 1 
AND a.`not_confirmed` IS NOT NULL 
AND e.`section_id` = 3 
AND [b]([/b]<START> BETWEEN b.`group_start` AND b.`group_end` 
OR <SLUT> BETWEEN b.`group_start` AND b.`group_end`[b])[/b]
```

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

## #4 — MickeA.com, 2011-08-22T05:44Z

> **[@nders skrev:](https://www.webforum.nu/p/1539108)**
>
> Kan det möjligen vara så att du vill att alla de första villkoren skall uppfyllas, samt (minst) ett av de två sista?
>
> ```
> WHERE a.not_user_id = 1 
> AND a.`not_type` = 1 
> AND a.`not_confirmed` IS NOT NULL 
> AND e.`section_id` = 3 
> AND [b]([/b]<START> BETWEEN b.`group_start` AND b.`group_end` 
> OR <SLUT> BETWEEN b.`group_start` AND b.`group_end`[b])[/b]
> ```

Ja, precis det vill jag!
Problemet just nu (som du säger) är ju att det blir fel, de datum man redan är bokad på ska "låsas" från vidare bokning (inom samma kategori), oavsett om det är start, slut eller hela perioden som på något vis krockar. Man ska däremot kunna boka plats för aktivitet som startar \_efter\_ tidigare boknings slutdatum, eller som slutar \_före\_ en redan bokad plats startdatum.

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

## #5 — @nders, 2011-08-22T05:45Z

Har du provat mitt förslag då?

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

## #6 — MickeA.com, 2011-08-22T07:53Z

> **[@nders skrev:](https://www.webforum.nu/p/1539110)**
>
> Har du provat mitt förslag då?

Jo, men det blir fortfarande fel. Vi kör ett exempel...

\- Jag är bokad till aktivitet 2011-09-01 - 2011-10-30.
\- Alla grupper vars start -eller slutdatum ligger inom dom två ska inte vara tillåtna.

I nuläget **får jag** boka in mig på aktivitet som pågår 2011-08-31 - 2011-12-01, eftersom både dom ligger före resp. efter start -och slutdatum på den redan bokade aktiviten.

Så frågan är, hur skyddar jag mig även mot detta scenario?

/R Min fråga ser ut såhär nu:

```
...
WHERE a.not_user_id = 1 
AND a.`not_type` = 1 
AND a.`not_confirmed` IS NOT NULL 
AND e.`section_id` = 3 
AND 
(
  '2011-08-31' BETWEEN b.`group_start` AND b.`group_end` 
  OR 
  '2011-12-01' BETWEEN b.`group_start` AND b.`group_end` 
)
```

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

## #7 — MickeA.com, 2011-08-22T08:02Z

Nu vände jag lite på frågan, nu blockeras även anmälan till aktivitet med datumen ovan. Frågan är vad jag förstört istället, ska testa lite mer..

```
...
WHERE a.not_user_id = 1 
AND a.`not_type` = 1 
AND a.`not_confirmed` IS NOT NULL 
AND e.`section_id` = 3 
AND 
(
  b.`group_start` BETWEEN '2011-08-01' AND '2011-08-31' 
  OR 
  b.`group_end` BETWEEN '2011-08-01' AND '2011-08-31' 
)
```

Nepp, blir såklart samma sak fast tvärtom, vilket är ännu sämre än det tidigare caset.

Finns det något sätt att lösa det här med en fråga, eller måste jag använda flera?

/R

Lade till ett extra OR-villkor:

```
...
WHERE a.not_user_id = 1 
AND a.`not_type` = 1 
AND a.`not_confirmed` IS NOT NULL 
AND e.`section_id` = 3 
AND (
  b.`group_start` BETWEEN '2011-12-02' AND '2011-12-15' 
  OR 
  b.`group_end` BETWEEN '2011-12-02' AND '2011-12-15' 
) 
OR 
(
  '2011-12-02' BETWEEN b.`group_start` AND b.`group_end` 
  OR '2011-12-15' BETWEEN b.`group_start` AND b.`group_end` 
)
```

Nu blockeras allt rätt. Har jag tänkt rätt nu?

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

## #8 — @nders, 2011-08-22T10:54Z

> Nu blockeras allt rätt. Har jag tänkt rätt nu?

Nej, som du har skrivit nu så räcker det med att det sista villkoret (din sista parentes) uppfylls. Sätt parenteser runt hela OR-villkoret.

```
AND
(
    (
      b.`group_start` BETWEEN '2011-12-02' AND '2011-12-15' 
      OR 
      b.`group_end` BETWEEN '2011-12-02' AND '2011-12-15' 
    ) 
    OR 
    (
      '2011-12-02' BETWEEN b.`group_start` AND b.`group_end` 
      OR '2011-12-15' BETWEEN b.`group_start` AND b.`group_end` 
    )
)
```

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

## #9 — MickeA.com, 2011-08-22T15:09Z

Jo såklart! Tack!

Ska testa imorrn, håller på att somna, börjar bli sent... Återkommer!

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

## #10 — MickeA.com, 2011-08-24T00:23Z

Hmm, något är lurt här.. Så här såg frågan ut från början (efter att jag gjort alla ändringar):

```
SELECT 
a.`not_id`, a.`not_type`, a.`not_confirmed`, 
b.`group_id` 
FROM `school_notifies` a 
INNER JOIN `school_group` b 
ON a.`not_group_id` = b.`group_id` 
  INNER JOIN `school_level` c 
  ON b.`group_parent` = c.`level_id` 
    INNER JOIN `school_type` d 
    ON c.`level_parent` = d.`type_id` 
      INNER JOIN `school_section` e 
      ON d.`type_parent` = e.`section_id` 
WHERE a.`not_confirmed` IS NOT NULL 
AND a.not_user_id = 1 
AND e.`section_id` = 3 
AND
(
  (
  b.`group_start` BETWEEN '2011-10-31' AND '2011-11-01' 
  OR 
  b.`group_end` BETWEEN '2011-10-31' AND '2011-11-01' 
  ) 
) 
OR 
(
  (
  '2011-10-31' BETWEEN b.`group_start` AND b.`group_end` 
  OR 
  '2011-11-01' BETWEEN b.`group_start` AND b.`group_end` 
  )
)
```

Upptäckte dock den hämtar rader **oavsett** användare, kategori eller om "not_confirmed" är NULL eller inte, **vad beror det på?**

Ändrade till det här:

```
SELECT 
a.`not_id`, a.`not_type`, a.`not_confirmed`, 
b.`group_id` 
FROM `school_notifies` a 
INNER JOIN `school_group` b 
ON a.`not_group_id` = b.`group_id` 
AND a.`not_confirmed` IS NOT NULL 
AND a.not_user_id = 1 
  INNER JOIN `school_level` c 
  ON b.`group_parent` = c.`level_id` 
    INNER JOIN `school_type` d 
    ON c.`level_parent` = d.`type_id` 
      INNER JOIN `school_section` e 
      ON d.`type_parent` = e.`section_id` 
WHERE 
(
  (
  b.`group_start` BETWEEN '2011-10-31' AND '2011-11-01' 
  OR 
  b.`group_end` BETWEEN '2011-10-31' AND '2011-11-01' 
  ) 
) 
OR 
(
  (
  '2011-10-31' BETWEEN b.`group_start` AND b.`group_end` 
  OR 
  '2011-11-01' BETWEEN b.`group_start` AND b.`group_end` 
  )
) 
AND e.`section_id` = 3
```

Alltså lade min WHERE-villkor som AND på "JOINEN" istället och då fungerar det.

Vad beror det här på? Är det någon GROUP BY eller så som saknas som orsakar det här?

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

## #11 — @nders, 2011-08-24T12:17Z

> Upptäckte dock den hämtar rader oavsett användare, kategori eller om "not_confirmed" är NULL eller inte, vad beror det på?

Du har fel på dina parenteser i WHERE. Du måste omsluta hela ditt OR-villkor, annars räcker det med att det sista villkoret uppfylls.

Titta på mitt förra inlägg och jämför hur jag satt parenteserna i koden mot hur du har skrivit parenteserna.

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

## #12 — MickeA.com, 2011-08-29T03:37Z

Lysande, nu fungerar det bättre! Tack!

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

---

Tråden på webben: https://www.webforum.nu/amne/databaser-sql/187610-mysql-skydd-mot-dubbelbokning-större-än-och-mindre-än
