Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a table to stores expiry dates of credit cards, below is the sample schema for table.
ExpiryDate Varchar(10)
Sample Data in Table is as follows:-
'08/10'
'09/11'
'08/16'
'10/17'
how can i find out if a card's date is expired?
I am not sure what you are expected, but You can use string manipulation with substring to get records those are not expired
Select *
FROM supportContacts
WHERE LEFT(ExpiryDate,2) >= MONTH(GETDATE()) AND RIGHT(ExpiryDate,2) >= RIGHT(YEAR(GETDATE()),2)
If you want expired card list then use this
Select *
FROM supportContacts
WHERE LEFT(ExpiryDate,2) < MONTH(GETDATE()) AND RIGHT(ExpiryDate,2) <= RIGHT(YEAR(GETDATE()),2)
SQL DEMO
With such an awful data structure you are forced to kludge this together. Here is one way of doing it.
with BadData as
(
select '08/10' as SemiDate union all
select '09/11' union all
select '08/16' union all
select '10/17'
)
select *
from BadData
where cast(replace(STUFF(SemiDate, 4, 0, '01-20'), '/', '-') as DATE) < CAST(getdate() as DATE)
If you stored the ExpirationDate as a date instead of a string this would be simple. I sure hope you aren't storing the credit card number alongside this.
select *
from billinginfo
where substring(expirydate,1,charindex('/',expirydate)-1) < month(getdate())
and '20'+ substring(expirydate,charindex('/',expirydate)+1, 2) <= year(getdate())
You can try this.
You want something like this:
select * from BillingInfo
where
cast(left(expiryDate, 2) as int) --take the month portion of the expiry date
< select datepart(mm, getdate()) --expiry month must be before current month
and
cast(right(expiryDate, 2) as int) --take the year portion of the expiry date
<= select datepart(yy, getdate()) % 1000 --expiry year must also be during or before current year
The % 1000 converts the year to two-digit format.
I guess you want this:
SELECT TOP 4 *
FROM BillingInfo
WHERE ExpiryDate in ('08/10','09/11','08/16','10/17')
This will find you the 4 items with those dates.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
How to get all the dates between start_date and end_date, including start_date and end_date?
But not those dates that do not fall in the range.
eg: 08-01-2020 should not be in the output because it is not in any of the work_id dates range
so 08-01-2020 is one of the non-working dates
So I want all the dates except the non-working dates.
Sample table :
Sample output :
either this
or this
Create a list of dates of target range, add working and non-working flags to the list, and filter by the flag.
You can get the expected output with the following query.
-- 1st, generate a list of dates
with dates as (
select min(start_date) as dates, max(end_date) as max_date from dates_range
union all
select dateadd(day, 1, dates), max_date from dates
where dates < max_date
),
-- 2nd, generate a list of dates with working/non working flag
all_dates as (
select distinct
d1.dates,
case when d2.work_id is not null then 'true' else 'false' end as working
from dates as d1 left outer join dates_range as d2
on d1.dates between d2.start_date and d2.end_date
)
-- 3rd, filter either that working is true or false
select dates as Non_working_dates from all_dates where working = 'false';
db<>fiddle
First you should create a table valued function that generates a list of dates for each entry in your table
CREATE FUNCTION DatesByRange(#start_date date, #end_date date)
RETURNS #Dates TABLE
(
Dates date
)
AS
BEGIN
WITH cteDateRanges AS
(
SELECT #start_date AS workday
UNION ALL
SELECT DATEADD(DAY, 1, workday) FROM cteDateRanges
WHERE workday < #end_date
)
INSERT INTO #Dates
SELECT workday FROM cteDateRanges
RETURN;
END;
Then you can use this function with a cross apply
SELECT DISTINCT x.* FROM YourTable
CROSS APPLY(SELECT * FROM dbo.DatesByRange(t.start_date, t.end_date)) x
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
For example DECLARE #a = 10;
Required output be like:
1) 16/5/2020
2) 15/5/2020
3) 14/5/2020
4) 13/5/2020
5) 12/5/2020
6) 11/5/2020
7) 10/5/2020
8) 9/5/2020
9) 8/5/2020
10) 7/5/2020
If Declare #b = 5 then get last five days of dates in output.
Snowflake:
SELECT DATEADD(DAY, -SEQ4(), CURRENT_DATE()) AS generated_date
FROM TABLE(GENERATOR(ROWCOUNT=>10))
ORDER BY generated_date desc;
SEQn() functions are not guaranteed to be gap free, so you need to use ROW_NUMBER()
WITH tally AS (
SELECT ROW_NUMBER() OVER(ORDER BY SEQ4()) AS rn
FROM TABLE(GENERATOR(ROWCOUNT=>10))
)
SELECT DATEADD(DAY, -rn, CURRENT_DATE()) AS generated_date
FROM tally
ORDER BY generated_date
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I need to create a trigger in SQL Server 2017 that will fire on INSERT and work off the CreatedDate column of my table.
The CreatedDate is of this format: 2017-09-21 07:15:59.883
What I want to do is check the time of the CreatedDate column and if it is between 7 and 8 I need to insert a value into a Notes column, if it is between 15 and 16 I need to insert another, if it is between 23 and 24 I need to insert another.
I am particularly stuck at the WHERE clause that I need to check the hour for. Not sure how to formulate this.
assuming your CreatedDate is datetime and not string
use datepart to checks for createdate hour and update the Notes column accordingly
UPDATE t
SET Notes = 'a value'
FROM inserted i
INNER JOIN mytable t ON i.pk = t.pk
WHERE datepart(hour, CreateDate) in (7, 8)
EDIT :
UPDATE t
SET Notes = case when datepart(hour, CreateDate) in ( 7, 8) then 'a value'
when datepart(hour, CreateDate) in (15, 16) then 'another value'
end
FROM inserted i
INNER JOIN mytable t ON i.pk = t.pk
WHERE datepart(hour, CreateDate) in (7, 8, 15, 16)
See datepart
where case when DATEPART ( HOUR, datetimeField ) =7 then someValue
case when DATEPART ( HOUR, datetimeField ) =15 then SomeOtherValue
case when DATEPART ( HOUR, datetimeField ) =23 then AnotherDiffetentValue
end
You can use DATEPART: https://learn.microsoft.com/en-us/sql/t-sql/functions/datepart-transact-sql
and CASE: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
I have the below query which works, however it seems very untidy and inefficient to me.
My table has two columns: TDate & Sales
TDate Sales
2016-03-25 5
2016-03-24 8
2016-03-28 7
2016-04-21 2
2016-04-14 1
I want to group the data by year and month, i.e. i don't care about the day part of the date. The result (which the query below does give) is,
TDate Sales
201603 20
201604 3
What is the best way to achieve this?
select left(convert(nvarchar, TDate, 112),6), sum(Sales)
from mytbl
group by left(convert(nvarchar, TDate, 112),6)
order by left(convert(nvarchar, TDate, 112),6)
convert the dates to first day(any static day) of month and do the grouping
Here is one way using EOMONTH
select dateadd(dd,1,eomonth(TDate,-1)) as Tdate,sum(sales)
from mytbl
Group by dateadd(dd,1,eomonth(TDate,-1))
Order by Tdate
or use DATEFROMPARTS
select DATEFROMPARTS(year(TDate),month(TDate),1)) as Tdate,sum(sales)
from mytbl
Group by DATEFROMPARTS(year(TDate),month(TDate),1))
Order by Tdate
This will make sure the dates are properly ordered. In your approach the dates are ordered as string. Both approaches work on Sql Server 2012 and above
For older versions
select DATEADD(mm, DATEDIFF(mm,0,TDate), 0) as Tdate,sum(sales)
from mytbl
Group by DATEADD(mm, DATEDIFF(mm,0,TDate), 0)
Order by Tdate
For me your query is OK but, maybe use of DATEPART instead of string conversion can be result more efficient as time spent.
Try this:
select DATEPART(year, TDate) *100 + DATEPART(month, TDate), sum(Sales)
from mytbl
group by DATEPART(year, TDate) *100 + DATEPART(month, TDate)
order by DATEPART(year, TDate) *100 + DATEPART(month, TDate)
Wrap your original query up in a derived table to save some typing, and also make it ANSI SQL compliant:
select TDate, sum(Sales)
from
(
select left(convert(nvarchar, TDate, 112),6) TDate, Sales
from mytbl
) dt
group by TDate
order by TDate
This way you don't have to write the same expression three times! (I.e. easier to adjust/maintain.)
(Same trick can be used for the other answers to the question.)
In SQL, I'd like to list all funds whose anniversary is due this year in 2 months time. What is the syntax?
SELECT *
FROM dbo.Funds
WHERE AnniversaryDate <= DATEADD(MONTH, 2, GETDATE())
That should work in SQL Server 2000 and up.
Marc
SELECT DATE_ADD(CURDATE(), INTERVAL 2 MONTH);
This will do it in MySQL. I haven't added the anniversary comparison because I don't know the structure of your tables.
I am not quite sure how to interpret your question, but it seems you are after something like this.
SELECT *
FROM funds
WHERE CURRENT_DATE <= anniversary
AND CURRENT_DATE > DATE_SUB(anniversary, INTERVAL 2 MONTH)
It is possibly not exact as I don't know which flavour of SQL you are using.
I don't know if "fund anniversary" is some kind of a special term in English, so I'm assuming you want to select something like the birthdays which can be stored with a random year, like 1972-01-03.
If it's not so, please correct me.
In SQL Server, you need to generate a list of years and join with it:
WITH q AS
(
SELECT 0 AS num
UNION ALL
SELECT num + 1
FROM q
WHERE num <= 100
)
SELECT *
FROM mytable
WHERE fund_date BETWEEN DATE_ADD(year, -num, GETDATE()) AND DATE_ADD(year, -num, DATE_ADD(month, 2, GETDATE()))
UNION ALL
SELECT *
FROM mytable
WHERE fund_date <= DATEADD(year, -100, GETDATE()
AND DATE_ADD(year, YEAR(GETDATE()) - YEAR(fund_date), fund_date) BETWEEN GETDATE() AND DATE_ADD(month, 2, GETDATE()))
This query is built in two parts:
The first part selects birthdays for each year from the list using the index range scans.
The second part selects birthdays that are more than 100 years old (using a single range scan) and filters them all.
Since birthdates older than 100 years are very unlike, the second part in fact selects almost nothing and does not affects performance too much.