SQL Query with date range Male Female - sql

I have a query that works but I need to incorporate in that query the following:
For male date is older or equals 3 months;
For female date is older or equals 4 months;
SELECT *
FROM Davaoci
WHERE DatumPoslednjegDavanja >= DATEADD(month, -3, GETDATE())
AND KrvnaGrupa = 'APos'
ORDER BY DatumPoslednjegDavanja DESC

Use a CASE statement:
SELECT * FROM Davaoci
WHERE DatumPoslednjegDavanja >= DATEADD(
month,
CASE WHEN Pol = 'M' THEN -3 ELSE -4 END,
GETDATE()
)
AND KrvnaGrupa = 'APos'
ORDER BY DatumPoslednjegDavanja DESC

EDITED: Based off your comments on the question, I made some adjustments to my answer. Working through our language barrier, I think this is what you're looking for.
NOTE: The way I have this set up now, it will only accept rows where the Pol column has an 'M' or 'F'. You may need to adjust the ELSE as needed.
SELECT *
FROM Davaoci
WHERE
KrvnaGrupa = 'APos'
AND CASE
WHEN Pol = 'M'
THEN DatumPoslednjegDavanja >= DATEADD(month, -3, GETDATE())
WHEN Pol = 'F'
THEN DatumPoslednjegDavanja <= DATEADD(month, -4, GETDATE())
ELSE FALSE
END
ORDER BY
DatumPoslednjegDavanja DESC;

Related

SQL Server - Null row not Showing?

Is there a way how to add null values rows, replacing with 0?
Ideally,I want to show data of all Month, if there is no data then count column set to zero.
Currently SQL query is not Returning Empty Rows and I'm getting output like this...
I'm using the code below to get the result set below that:
SELECT
DATENAME(MONTH,A.Date) 'Month', COUNT(LateStatus) 'Count', 'Late' 'Type'
FROM
Attendance1 A
WHERE
A.EnrollId = '10000' AND A.Date BETWEEN '2016-01-01' AND '2016-08-31' AND LateStatus = 'L'
GROUP BY
DATENAME(MONTH,A.Date)
Use a recursive CTE (dynamically makes a calendar table):
With Months(mon) As
(Select dateAdd(month, datediff(month, 365, getdate()), 0)
Union All
Select DateAdd(month, 1, mon) from Months
Where mon < getdate())
Select DATENAME(MONTH, m.mon ) 'Month',
COUNT(LateStatus) 'Count', 'Late' 'Type'
FROM months m
left join Attendance1 a
on a.Date between m.mon and dateadd(month, 1, m.mon)
and a.EnrollId = '10000'
and a.LateStatus = 'L'
GROUP BY DATENAME(MONTH, m.Mon)
A more generic function, to generate a range of integers which can be used for any expression, is this:
create function dbo.NumberList (#start integer, #end integer)
returns table
as Return
(
With ints(aInt) As
(Select #start Union All
Select aInt + 1 From ints
Where aInt < #end)
Select aInt from ints
)
Once this function has been created, you can use it to dynamically create any range of values of any type:
For months from 8 months ago to 3 months ago
Select i.aInt, Dateadd(month, i.aInt,
DateAdd(month, datediff(month(0, getdate()), 0))
From dbo.NumberList(-8, -3) i
Assuming you have some data for all months, you can do this using conditional aggregation. That is, move the WHERE conditions to the SELECT using CASE:
SELECT DATENAME(MONTH,A.Date) as Mon,
SUM(CASE WHEN A.EnrollId = '10000' AND LateStatus = 'L'
THEN 1 ELSE 0
END) as cnt,
'Late' as 'Type'
FROM Attendance1 A
WHERE AND A.Date BETWEEN '2016-01-01' AND '2016-08-31'
GROUP BY DATENAME(MONTH, A.Date)
ORDER BY MIN(A.Date);
There are other methods, usually involving LEFT JOIN. But this is the simplest if it solves the problem.

SQL Server query to get data for last two months

SELECT
DAY(table_A.PaymentDate) as date1 ,
(CASE
WHEN MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP)
THEN CAST(SUM(table_A.Total_Amount) As INT)
ELSE 0
END) AS This_month_CNT,
(CASE
WHEN MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP) - 1
THEN CAST(SUM(table_A.Total_Amount) AS INT)
ELSE 0
END) AS last_month_CNT
FROM
Tbl_Pan_Paymentdetails table_A
FULL OUTER JOIN
Tbl_Pan_Paymentdetails table_B ON table_A.PaymentDate = table_B.PaymentDate
WHERE
YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND table_A.PaymentDate >= DATEADD(MONTH, -2, GETDATE())
GROUP BY
DAY(table_A.PaymentDate),
MONTH(table_A.PaymentDate)
ORDER BY
DAY(table_A.PaymentDate) ;
Not sure I fully understand.
WHERE YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP) AND
table_A.PaymentDate >= DATEADD(MONTH, -2, GETDATE())
Here you are (1) comparing the Year elements of your payment date with CURRENT_TIMESTAMP, and (2) making sure the payment date is greater than the last 2 months based on GETDATE()?
Not sure why you are using both CURRENT_TIMESTAMP and GETDATE(). Either way, I think the second part of that WHERE statement does what you want.
If the current date is January 31, 2015, your currently logic will not return any records from December 2014. The first part of your where statement is filtering them out. If you really want the last 2 months, remove the following from the WHERE statement
YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP) AND

Sum on case expression when working with dates

I'm looking to create a view which will output the data in the following format
AgedPeriod BillValue Status
<1 35000 Outstanding
1-3 23386 Outstanding
3-6 5000 Outstanding
I can use the code below to SUM each case statement into a new column and I could name the column headings after the AgedPeriod listed above but even though the SUMS are right the format is wrong I would like to have the code below nested in another CASE statement that does not have to be GROUPED by b.BILL_DATE as grouping with the bill date defeats the purpose of my SUM. All attempts as using another CASE statement always bring the b.BILL_DATE out of the SUM and into the WHEN condition requiring it to be grouped.
SELECT
SUM(CASE WHEN (b.BILL_DATE <= GetDate()
AND b.BILL_DATE >= DateAdd(mm,-1, GetDate()))
THEN b.OUTSTANDING END),
SUM(CASE WHEN (b.BILL_DATE <= DateAdd(mm,-1, GetDate())
AND b.BILL_DATE >= DateAdd(mm,-3, GetDate()))
THEN b.OUTSTANDING END),
SUM(CASE WHEN (b.BILL_DATE <= DateAdd(mm,-3, GetDate())
AND b.BILL_DATE >= DateAdd(mm,-6, GetDate()))
THEN b.OUTSTANDING END)
FROM dbo.Tables
I understand this may not be achievable with the route that I have taken at present but is there be any other way I can SUM the outstanding amount on each time period? I can deal with the status column (no advice needed there)
I have added a table and some sample data and left a query to show how I would want the data split up but it would want it to be formatted as above (in a column)
Example on Sql Fiddle
Thanks
You want a group by rather than conditional aggregation. The query you want is something like this:
SELECT (CASE WHEN b.BILL_DATE >= DateAdd(month,-1, GetDate())
THEN '<1'
WHEN b.BILL_DATE >= DateAdd(month, -3, GetDate())
THEN '1-3'
WHEN b.BILL_DATE >= DateAdd(month, -6, GetDate())
THEN '3-6'
ELSE '6+'
END) as AgedPeriod,
SUM(Outstanding)
FROM dbo.Tables b
WHERE b.BILL_DATE <= GetDate()
GROUP BY (CASE WHEN b.BILL_DATE >= DateAdd(month,-1, GetDate())
THEN '<1'
WHEN b.BILL_DATE >= DateAdd(month, -3, GetDate())
THEN '1-3'
WHEN b.BILL_DATE >= DateAdd(month, -6, GetDate())
THEN '3-6'
ELSE '6+'
END);
Notes:
The groups are defined by a CASE statement. Because this is evaluated in order, you can simplify the logic.
The common condition b.BILL_DATE <= GetDate() is moved to the WHERE clause.
I added an extra condition for longer than six months. It seems like you wouldn't want to ignore these.
I don't know what the final column is supposed to be.
You could either use a subquery or CTE to perform the case when statement and then join back to the base table to get the sum for the outstanding column like this:
SELECT a.AgedPeriod
,sum(t1.Outstanding) BillValue
,a.[Status]
FROM dbo.Bill t1
JOIN (
SELECT (
CASE
WHEN b.BILLDATE >= DateAdd(month, - 1, GetDate())
THEN '<1'
WHEN b.BILLDATE >= DateAdd(month, - 3, GetDate())
THEN '1-3'
WHEN b.BILLDATE >= DateAdd(month, - 6, GetDate())
THEN '3-6'
ELSE '6+'
END
) AS AgedPeriod
,b.[ID]
,'Outstanding' [Status]
FROM dbo.Bill b
WHERE b.BILLDATE <= GetDate()
) a ON a.[ID] = t1.[ID]
GROUP BY a.AgedPeriod
,a.[Status]
Hope this helps! Here is a SQL Fiddle Demo for this:
SQL Fiddle Solution Demo

SQL - Display running count of appointments grouped by time frame

I have a table
tblAppointment {
App_ID,
App_Date,
User_ID }
I currently have a statement that returns number of appointments grouped by year and month
SELECT
YEAR(App_Date) AS Year,
MONTH(App_Date) AS Month,
count(*) AS "No of Appointments"
FROM
tblapplication
GROUP BY
YEAR(App_Date),
MONTH(App_Date)
Im not sure how to write a select statement to return it with headings {time frame, No of applications}, and then have data in
row 1: time frame = week thus far, no of app = x.
row 2: time frame = month thus far, no of app = y.
ro3 3: time frame = year so far, no of app - z.
I would like to know how many appointments there are for 1. the current week, 2. the current month. 3. the current year, And have each result in its own row.
Any help in the right direction would be greatly appreciated. The actual problem is much greater than this but believe I have simplified it to the crux of the matter for now.
If you're okay with the results on one row, it's relatively easy:
select count(case when datepart(wk, App_Date) = datepart(wk, getdate())
then 1 end) as WeekSofFar
, count(case when datepart(m, App_Date) = datepart(m, getdate())
then 1 end) as MonthSofFar
, count(*) as YearSoFar
from tblApplications
where datepart(y, App_Date) = datepart(y, getdate())
If the separate rows are a must-have, try something like:
select 'WeekSoFar' as Period
, (
select count(*)
from tblApplications
where datepart(y, App_Date) = datepart(y, getdate())
and datepart(wk, App_Date) = datepart(wk, getdate())
) as NumberOfApps
union all
select 'MonthSoFar'
, (
select count(*)
from tblApplications
where datepart(y, App_Date) = datepart(y, getdate())
and datepart(m, App_Date) = datepart(m, getdate())
)
union all
select 'YearSoFar'
, (
select count(*)
from tblApplications
where datepart(y, App_Date) = datepart(y, getdate())
)
I assumed SQL 2008 as you didn't specify.
SELECT
X.TimePeriod,
Count(
CASE X.Which
WHEN 3 THEN
CASE
WHEN App_Date > DateAdd(Day, -DatePart(Weekday, GetDate()), GetDate())
THEN 1
END
WHEN 2 THEN CASE WHEN Month(App_Date) = Month(GetDate()) THEN 1 END
ELSE 1 END
) [No of Appointments]
FROM
tblApplication
CROSS JOIN (
VALUES (1, 'Year to date'), (2, 'Month to date'), (3, 'Week to date')
) X (Which, TimePeriod)
WHERE
App_Date < Convert(date, GetDate() + 1)
AND App_Date >= DateAdd(Year, DateDiff(Year, '19000101', App_Date), '19000101')
GROUP BY
X.Which,
X.TimePeriod
ORDER BY
X.Which
If you have a lot of data in your table and an index on App_Date, this query will perform hugely better than one using date functions on the entire table without filtering.
I also have an embedded assumption that your App_Date values have no time portion (they are all set to 12am). If this is not true please let me know so I can modify case 3 to be correct.
If anyone wants to try the code here's some setup:
CREATE TABLE tblApplication (
App_Date datetime
)
INSERT tblApplication
VALUES
('2/1/2012'), ('2/5/2012'), ('2/10/2012'), ('1/2/2012'), ('1/9/2012'),
('1/15/2012'), ('1/28/2012'), ('12/1/2012'), ('12/5/2012'), ('12/10/2012'),
('11/2/2012'), ('11/9/2012'), ('11/15/2012'), ('11/28/2012')
Sorry about not using 'YYYYMMDD', I wasn't thinking when I typed it out.

Check if DateTime in DB is more than 90 days old via Stored Procedure

UPDATE
Evidently I didn't include enough data, sorry!
What I need to do is set 'campaign_Status' = 6 when 'campaign_Date' is more than 90 days old.
Hi,
I have a column (campaign_Date) which stores a DATETIME. Using a Stored Procedure I need to check if the stored date is 90 days old (or more).
Any help would be great.
Thanks.
This will return all old campaigns:
SELECT *
FROM mytable
WHERE campaign_Date <= DATEADD(day, -90, GETDATE())
This will select 1 if campaign is old, 0 otherwise:
SELECT CASE WHEN campaign_Date <= DATEADD(day, -90, GETDATE()) THEN 1 ELSE 0 END
FROM mytable
Note that the first query condition is sargable: it will allow using an index to filter the dates.
This will update all old campaigns with status 6:
UPDATE mytable
SET campaign_status = 6
WHERE campaign_Date <= DATEADD(day, -90, GETDATE())
See the DateAdd function
http://msdn.microsoft.com/en-us/library/ms186819.aspx
SELECT *
FROM MyTable
WHERE Campaign_Date <= DateAdd (d, -90, GetDate())
Here's a variation on the previous answers, wrapped in a stored procedure (as seemed to be asked):
CREATE PROC sp_Campaign_Archive AS
UPDATE [Campaign Table]
SET Campaign_Status = 6
WHERE DateDiff(day,Campaign_Date,GetDate()) >= 90
GO
SELECT IIF(DATEDIFF(d, campaign_date, getdate()) >= 90, true, false)
AS IsNinetyOrMoreDaysOld
FROM myTable
EDIT: If you wish to pick records which are 90 or more days old,
SELECT campaign_date
FROM myTable
WHERE DATEDIFF(d, campaign_date, getdate()) >= 90
select campaign_Date,
case when getdate() - campaign_Date >= 90 then 'yes' else 'no' end as Is90DaysOldOrMore
from MyTable
UPDATE:
You can update the records like this:
update MyTable
set campaign_Status = 6
where getdate() - campaign_Date >= 90
Because this status will go out of date rapidly because it is date-dependent, you could make it a calculated column instead.