views:

99

answers:

5

I have table like this

create table tbl_1(
  year int,
  month int, 
 day int
)

insert into tbl_1 values(2009,  11, 30)
insert into tbl_1 values(2010,   3,  4)
insert into tbl_1 values(2011,   5, 13)
insert into tbl_1 values(20011, 12, 24)

I want to delete date from 2009-11-30 until 2011-5-13, but I can't because all of columns are int and I can't use this query :

delete from tbl_1 
 where year >=2009 
   and year<=2011 
   and month >=11 
   and month <=5 
   and day >=30 
   and day <=13

..because: 1 < month < 12 and 1 < day < 30

I know that this is terrible mistake.

I have many table that use this way for save date , please help me I don't have time to delete and recreate all of them.

+3  A: 

Just use some more boolean operators:

DELETE FROM tbl_1
WHERE (year = 2009 AND (month > 11 OR (month = 11 AND day >= 30)))
OR year = 2010
OR (year = 2011 AND (month < 5 OR (month = 5 AND day <= 13)))

Not pretty, but it works.

Edit:

parametrized:

DELETE FROM tbl_1
WHERE (year = %minYear% AND (month > %minMonth% OR (month = %minMonth% AND day >= %minDay%)))
OR (year > %minYear% AND year < %maxYear%)
OR (year = %maxYear% AND (month < %maxMonth% OR (month = %maxMonth% AND day <= %maxDay%)))
Jasper
Edited the comparisons.
Quassnoi
tank you for your helping,but i use C# program and user select date and this query is limited ,just for 2009 until 2011 and I won't know which date the user select.
mahnaz
That makes it only slightly harder. It's some work, but it is doable to change this into a parameterized query.
Jasper
@Quassnoi: Ah thanks!
Jasper
@mahnaz: there you go!
Jasper
+7  A: 

You could do it like this:

DELETE FROM tbl_1 
WHERE (year * 10000 + month * 100 + day) BETWEEN 20091130 AND 20110513

I haven't tested this. I would recommend testing it first on a test system before running it on your production data so that you don't accidentally delete the wrong data.

Mark Byers
That's a lot cuter than what I did for sure...
Jasper
@Jasper: But this wouldn't be able to use an index, while yours could.
OMG Ponies
thank you this way worked in my sql,and u solved my problem. thank you very much from all
mahnaz
+4  A: 

In MySQL and PostgreSQL:

DELETE
FROM    tbl_1
WHERE   (2009, 11, 30) <= (year, month, date)
        AND (year, month, date) <= (2011, 5, 13)

In PostgreSQL you can even do:

DELETE
FROM    tbl_1
WHERE   (year, month, date) BETWEEN (2009, 11, 30) AND (2011, 5, 13)
Quassnoi
You and your tuples...
OMG Ponies
Can you explain how this works please> If (a,b,c) < (x,y,z) is just a shorthand way of saying a < x and b < y and c < z then I don't think this is correct. If that's not the case then I'd like to know more about this syntax.
Chris Simpson
@Chris: http://en.wikipedia.org/wiki/Lexicographical_order
Quassnoi
that took a few re-reads this late in the day. Thanks for the link. Not sure I follow the partial order thing but I understand cartesian products and I believe can see how that would work now. It's actually quite similar to @Mark's answer then.
Chris Simpson
@Chris Simpson: My answer uses only standard SQL. This is vendor specific and I think it's unlikely to work on the OPs system (most likely SQL Server). But I +1ed this answer anyway.
Mark Byers
@Chris: Unfortunately, simple English version is not yet there. But @Jasper's answer illustrates the principle quite well, mine one is just formulated more elegantly (though it won't work in `SQL Server`)
Quassnoi
A: 

Convert the columns to date in your where clause then:

DELETE tbl_1
WHERE CONVERT(DATETIME, CONVERT(VARCHAR(4), year) + '-' + convert(VARCHAR(2), month) + '-' + CONVERT(VARCHAR(2), day)) BETWEEN '20091130' AND '20110513'
Chris Simpson
when I used this query in sql server,it showed error to meMsg 241, Level 16, State 1, Line 1Conversion failed when converting date and/or time from character string.what can I do?
mahnaz
that's strange. the BETWEEN '20091130' AND '20110513' is using implicit conversion that will fail this way if invalid dates are used. Perhaps you are missing digits from one of these? Alternatively do you have any rows in the table that do not form a valid date?
Chris Simpson
A: 

Easiest way to do this is to use DATE_FORMAT. Like so:

...
WHERE DATE_FORMAT( CONCAT(year,"-",month,"-",day), '%Y-%m-%d' ) > "2009-11-30"
AND DATE_FORMAT( CONCAT(year,"-",month,"-",day), '%Y-%m-%d' ) < "2011-05-13"

Hope this helps! :-)

Cricket La Chica
I use sql server 2008 and it said :Msg 195, Level 15, State 10, Line 2'CONCAT' is not a recognized built-in function name. this function is difrence in 2008?
mahnaz