2010-07-06 13 views
2

je stocker des intervalles dans le SQL, par exemple:Vérifiez intervalle de temps en utilisant la condition SQL

id INT 
from DATE 
to DATE 

Comment puis-je vérifier, en utilisant une seule condition (si possible) si un conflit intervalle NOUVEA existant ?

Exemples:

|-----------| (from 1 to 5) 
    |-----------| (from 2 to 6) 
     |--| (from 3 to 4) 
        |--| (from 7 to 8) 

Chaque intervalle (dans les trois premiers) a un conflit avec les deux autres intervalles ... sauf le dernier qui est seul.

-

Cette vérification peut être réalisée en utilisant une certaine condition comme:

WHERE (`from` <= $FROM and `to` >= $TO) 

Mais cela ne intervalles cocher contient le nouveau ... Pas les autres intervalles qui a une certaine intersections OU ceux qui est à l'intérieur le nouveau.

Peut-être que quelque chose comme ça?

WHERE NOT (`from` < $FROM and `to` < $TO) AND NOT (`from` > $FROM and `to` > $TO) 

Obs .: Je dois trouver les collisions pour alerter l'utilisateur que cette nouvelle période existent déjà ou entrer en conflit avec un un existin.

+0

Quelle représentation des périodes utilisez-vous, par ex. fermé-ouvert? Autrement dit, considéreriez-vous '(de 1 à 5)' entrer en collision avec '(de 5 à 6)'? – onedaywhen

Répondre

2
WHERE ($TO >= `from` AND $FROM <= `to`) 

Notez que cela fonctionne pour le cas où la nouvelle gamme chevauche la gamme, quand il ne recouvre partiellement et quand elle englobe aussi bien.

+0

+1, question d'entrevue d'emploi classique :) – Konerak

+0

WTF! Tu es un génie! –

+0

Je travaillais dans les systèmes SIG dans les années 80. Les intersections et les chevauchements sont une seconde nature pour moi. –

3

Je suis tombé sur cette question et je voulais juste essayer de montrer comment une table de vérité peut identifier la logique réduite que Paul a déjà posté.

Supposons que vous ayez un intervalle from [ to ] que vous souhaitez vérifier par rapport à from { to }.

Cela se traduit par la table de vérité suivante:

# [ < { [ < } ] < { ] < } Collision? Example 
1  T  T  T  T   F  [ ] { } 
2  T  T  T  F   T  [ } { ] * 
3  T  T  F  T   T  [ { ] } 
4  T  T  F  F   T  [ { } ] 
5  T  F  T  T   T  ] } [ { * 
6  T  F  T  F   T  } [ ] { * 
7  T  F  F  T   Contradiction 
8  T  F  F  F   T  } [ { ] * 
9  F  T  T  T   T  ] { [ } * 
10  F  T  T  F   Contradiction 
11  F  T  F  T   T  { [ ] } 
12  F  T  F  F   T  { [ } ] 
13  F  F  T  T   T  ] { } [ * 
14  F  F  T  F   T  } ] { [ * 
15  F  F  F  T   T  { ] } [ * 
16  F  F  F  F   F  { } [ ] 

En regardant cette table de vérité, l'expression la plus simple d'identifier les collisions est:

NOT ([ < { AND [ < } AND ] < { AND ] < }) AND NOT ([ >= { AND [ >= } AND ] >= { AND ] >= })

Cependant, nous savons que, depuis { < } et [ < ], ceci se réduit à

NOT ([ < { AND ] < {) AND NOT ([ >= } AND ] >= })

qui correspond à la SQL:

WHERE NOT ('from' < $FROM and 'to' < $FROM) AND NOT ('from' > $TO and 'to' > $TO) (semblable à ce que @TiuTalk suggéré). Toutefois, nous avons déjà supposé que { < } et [ < ]. C'est critique. Regardez les lignes marquées * dans la table de vérité. Dans ces rangées, } < { ou ] < [. Nous savons que cela n'arrivera pas.De plus, certaines lignes impliquent des choses complètement contradictoires comme } < { AND { < } que nous savons être impossible. L'élimination de toutes ces lignes donne seulement 6 lignes:

# [ < { [ < } ] < { ] < } Collision? Example 
1  T  T  T  T   F  [ ] { } 
3  T  T  F  T   T  [ { ] } 
4  T  T  F  F   T  [ { } ] 
11  F  T  F  T   T  { [ ] } 
12  F  T  F  F   T  { [ } ] 
16  F  F  F  F   F  { } [ ] 

Ici, nous pouvons voir que seulement les deux intermédiaires clauses déterminent s'il y a une collision. A savoir, ([ < }) AND NOT (] < {). Ceci est équivalent à ([ < }) AND (] >= {) (en supprimant le deuxième comparateur) qui est équivalent au SQL WHERE ('from' < $TO AND 'to' >= $FROM). Ceci est sémantiquement équivalent à la clause de Paul (sauf travailler à travers la <= jusqu'à la fin).