Calculate Days Present and absent from the table - sql

I have a table name Emp_mon_day which consists Employees Present and Absent details.
What I want is
I need for these 9 employees, information about days present and days absent for each employees from Emp_mon_day table merged in to below query
QUERY
SELECT e.comp_mkey,
e.status,
e.resig_date,
dt_of_leave,
e.emp_name,
e.date_of_joining,
e.emp_card_no,
a.pl_days,
pl_days_opening,
a.month1,
a.month2,
a.month3,
a.month4,
a.month5,
a.month6,
a.month7,
a.month8,
a.month9,
a.month10,
a.month11,
a.month12,
a.month1 + a.month2 + a.month3 + a.month4 + a.month5 + a.month6 + a.month7 + a.month8 + a.month9 + +a.month10 + a.month11 + a.month12 AS pl_sum
FROM p_leave_allocation AS a
INNER JOIN
emp_mst AS e
ON a.emp_card_no = e.emp_card_no
WHERE a.year = 2016
AND (datediff(MONTH, e.date_of_joining, CONVERT (DATETIME, getdate(), 103)) >= 6
AND datediff(MONTH, e.date_of_joining, CONVERT (DATETIME, getdate(), 103)) <= 36)
AND (e.resig_date IS NULL
OR (e.dt_of_leave IS NOT NULL
AND e.dt_of_leave >= CONVERT (DATETIME, getdate(), 103)))
AND e.status IN ('A', 'S')
AND e.comp_mkey IN (7, 110)
AND a.Year = 2016;
The above query gives me data as below
[![Image data][1]][1]
Column details for Emp_mon_day is below
[![enter image description here][2]][2]

You can try the below query:
SELECT e.comp_mkey, e.status, e.resig_date, dt_of_leave, e.emp_name,
e.date_of_joining, e.emp_card_no, a.pl_days, pl_days_opening, a.month1,
a.month2, a.month3, a.month4, a.month5, a.month6, a.month7, a.month8,
a.month9, a.month10, a.month11, a.month12,
a.month1 + a.month2 + a.month3 + a.month4 + a.month5 + a.month6 + a.month7 + a.month8 + a.month9 + +a.month10 + a.month11 + a.month12 AS pl_sum,
m.[DaysAbsent],m.[DaysPresent]
FROM p_leave_allocation AS a
INNER JOIN
emp_mst AS e
ON a.emp_card_no = e.emp_card_no
INNER JOIN
(
SELECT
comp_mkey,emp_mkey,[month],[year],
SUM(CASE WHEN data ='AB' THEN 1 ELSE 0 END) AS [DaysAbsent],
SUM(CASE WHEN data ='P' THEN 1 ELSE 0 END) AS [DaysPresent]
FROM
(
SELECT comp_mkey,emp_mkey,[month],[year],[Day1],[Day2],[Day3],[Day4],[Day5]
--,...
FROM Emp_mon_day
) source
UNPIVOT
(
data FOR day IN ([Day1],[Day2],[Day3],[Day4],[Day5]) -- dynamic query can generate all days data
)up
GROUP BY comp_mkey, emp_mkey,[month],[year]
) AS m
ON m.comp_mkey=e.Comp_mkey and m.emp_mkey=e.mkey
--- ABOVE CRITERIA NEEDS TO BE CHECKED
WHERE a.year = 2016
AND (datediff(MONTH, e.date_of_joining, CONVERT (DATETIME, getdate(), 103)) >= 6
AND datediff(MONTH, e.date_of_joining, CONVERT (DATETIME, getdate(), 103)) <= 36)
AND (e.resig_date IS NULL
OR (e.dt_of_leave IS NOT NULL
AND e.dt_of_leave >= CONVERT (DATETIME, getdate(), 103)))
AND e.status IN ('A', 'S')
AND e.comp_mkey IN (7, 110)
AND a.Year = 2016;
Explanation:
We've added another INNER JOIN to the existing query to get collated data of DaysPresent and DaysAbsent
To optimize this further, I'd suggest you directly apply following WHERE clause to source set
WHERE comp_mkey IN (7, 110) AND Year = 2016;

Related

Sql where Condition execution not working

I have the following query logic
Show comments which is not deleted
Show comments which is deleted after created, within a timespan of 30 days before today(Today - Createddate <= 30)
Below is the logic which I wrote, but I don't think it is working correct.
SELECT string_agg(
CAST(CONCAT_WS(',',
c.Id,
COALESCE(c.ParentCommentId, 0),
c.TotalRatingsCount,
c.Pinned,
c.IsDeleted,
FORMAT(c.CreatedDate, 'yyyy-MM-dd HH:mm:ss')) AS VARCHAR(MAX))
, '|')
FROM Comments c
WHERE c.DiscussionId = d.Id
and
((c.IsDeleted = 0 and DATEDIFF(day, c.CreatedDate , GETDATE()) >= 30))
or
(((c.IsDeleted = 1 or c.IsDeleted =0) and DATEDIFF(day, c.CreatedDate , GETDATE()) <= 30))
SELECT string_agg(
CAST(CONCAT_WS(',',
c.Id,
COALESCE(c.ParentCommentId, 0),
c.TotalRatingsCount,
c.Pinned,
c.IsDeleted,
FORMAT(c.CreatedDate, 'yyyy-MM-dd HH:mm:ss')) AS VARCHAR(MAX))
, '|')
FROM Comments c
WHERE c.DiscussionId = d.Id
and
((c.IsDeleted = 0 )
or
((c.IsDeleted = 1 ) and DATEDIFF(day, c.CreatedDate , GETDATE()) <= 30))

Get OrderTotal by hourly for current date gives subquery error :

Here is my SQL query which presently gives hourly order data for current the date. Here I need to count order by following case when condition, if I add this I am getting sub-query error after 11:00 AM, Please anybody help me out to solve problem.
Following SQL query on which I am performing:
DECLARE #intervalMinutes int = 60
DECLARE #schedule table (
myId int primary key identity,
startTime time,
endTime time
)
DECLARE #startTime time= '12:00:00 AM';
DECLARE #endTime time='11:00:00 PM';
;WITH CTE AS
(
SELECT #startTime st
UNION ALL
SELECT DATEADD(MINUTE,#intervalMinutes,st)
FROM cte
WHERE st < DATEADD(MINUTE,#intervalMinutes,st)
)
INSERT INTO #schedule(startTime,endTime)
SELECT st, DATEADD(MINUTE,#intervalMinutes,st)FROM cte
SELECT CONVERT(varchar(10), startTime, 100) + ' - ' + CONVERT(varchar(10), endTime , 100) AS TimeSlots,
ISNULL((SELECT CASE WHEN ISNULL(O.isAfterDiscount,0) != 0 THEN ((O.SubTotal - Total_Discount) + O.Total_Tax)
ELSE ((O.SubTotal + O.Total_Tax) - Total_Discount)
END AS OrderTotal FROM [dbo].[Order] AS O WHERE O.Order_Status='COMPLETED' AND
(O.CreatedDate >= CAST(CONVERT(varchar(20), GETUTCDATE(),101) + ' ' + CONVERT(varchar(8), startTime, 108) as datetime))
AND (O.CreatedDate <= CAST(CONVERT(varchar(20), GETUTCDATE(),101) + ' ' + CONVERT(varchar(8), REPLACE(endTime,'00:00:00.000','23:59:59.999'), 108) as datetime))),0) AS TotalSales
FROM #schedule
The following error comes while execute query:
Msg 512, Level 16, State 1, Line 22
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The following query results which I need to display:
Please guide me on this.
It means, you have got many values comes from Order table subquery. You have to apply SUM aggregate function to sum over the sales amount from order table.
SELECT CONVERT(VARCHAR(10), startTime, 100) + ' - ' + CONVERT(VARCHAR(10), endTime, 100) AS TimeSlots
,ISNULL((
SELECT SUM(CASE WHEN ISNULL(O.isAfterDiscount, 0) != 0 THEN ((O.SubTotal - Total_Discount) + O.Total_Tax) ELSE ((O.SubTotal + O.Total_Tax) - Total_Discount) END) AS OrderTotal
FROM [dbo].[Order] AS O
WHERE O.Order_Status = 'COMPLETED'
AND (O.CreatedDate >= CAST(CONVERT(VARCHAR(20), GETUTCDATE(), 101) + ' ' + CONVERT(VARCHAR(8), startTime, 108) AS DATETIME))
AND (O.CreatedDate <= CAST(CONVERT(VARCHAR(20), GETUTCDATE(), 101) + ' ' + CONVERT(VARCHAR(8), REPLACE(endTime, '00:00:00.000', '23:59:59.999'), 108) AS DATETIME))
), 0) AS TotalSales
FROM #schedule

Conversion of string to DateTime & using conversion in Where Clause - DateDiff

I have a string column that contains dates. I want to convert string to date so that i can use the Date Logic ahead.
I have converted the string to DateTime but while applying the logic in the Where clause it doesn't allow me to use the Column.
SELECT a.code,
CONVERT(DATETIME,b.[FieldValue],103) as [Date1]
FROM [dbo].employeedetail as A join [dbo].CustomeFieldDetail as B
on A.Id = B.EMployeeid
WHERE a.empstatus = 1
AND B.CustomeFieldName = 'PASSPORT' AND
( Datediff(dd, Getdate(), Dateadd(yyyy, Datediff(yyyy, b.[Date1],
Getdate())
+
1, b.[Date1]))
+ 1 ) % 366 = 50
Can anyone help me?
Use APPLY to introduce a reusable expression.
SELECT a.code,
c.[Date1]
FROM [dbo].employeedetail as A
JOIN [dbo].CustomeFieldDetail as B ON A.Id = B.EMployeeid
CROSS APPLY (
SELECT CONVERT(DATETIME,b.[FieldValue],103) as [Date1]
) c
WHERE a.empstatus = 1
AND B.CustomeFieldName = 'PASSPORT' AND
( Datediff(dd, Getdate(), Dateadd(yyyy, Datediff(yyyy, c.[Date1],
Getdate())
+
1, c.[Date1]))
+ 1 ) % 366 = 50
A better solution is store dates as DATE, DATETIME, not strings.
Using CTE results in an even more compact query:
WITH B AS (
SELECT *, CONVERT(DATETIME, [FieldValue], 103) AS [Date1]
FROM [dbo].CustomeFieldDetail
WHERE (CustomeFieldName = 'PASSPORT')
)
SELECT A.code, B.[Date1]
FROM [dbo].EmployeeDetail AS A JOIN B ON A.Id = B.EMployeeid
WHERE (A.empstatus = 1)
AND (((DATEDIFF(dd, GETDATE(),
DATEADD(yyyy, DATEDIFF(yyyy, B.[Date1], GETDATE()) + 1, B.[Date1])) + 1)
% 366) = 50)

How to show monthly data even if there are no results yet SQL Server 2008

So I wrote a script that would show monthly premium. Say if you want to view the total premium up to November, you can pass through a parameter in in SSRS to pick 1/1/2016 - 11/30/2016. This would only show the data up until november, hoever, I would like to show it up until december even if there are no records there. How do I go about doing this in SQL? Here is my script so far:
SELECT lc.[Date]
,lc.Carrier
,lc.[Direct Ceded Written Premium]
,cast(cast(year(lc.[date]) as varchar(4)) + '-' + cast(month(lc.[date]) as varchar(2)) + '-01' as date) as [begofmonth]
from
(
SELECT
CASE
WHEN pd.TransactionEffDate < pd.TransactionDate THEN cast(pd.TransactionDate as DATE)
WHEN pd.TransactionEffDate < pd.EffectiveDate THEN cast(pd.EffectiveDate as DATE)
ELSE cast(pd.TransactionEffDate as date)
END AS [Date]
,CASE WHEN LEFT(PD.POLICYNUM, 3) = 'ORV'
THEN 'Palomar Value Select OR'
WHEN LEFT(PD.POLICYNUM, 3) = 'VSE'
THEN 'Palomar Value Select CA'
WHEN LEFT(PD.POLICYNUM, 3) = 'WAV'
THEN 'Palomar Value Select WA'
ELSE 'Palomar' END AS [Carrier]
,ISNULL(SUM(pd.WrittenPremium), 0) AS [Direct Ceded Written Premium]
FROM premdetail pd
JOIN transactionpremium tp ON pd.systemid = tp.systemid
AND pd.transactionpremiumid = tp.id
JOIN transactionhistory th ON tp.systemid = th.systemid
AND tp.cmmcontainer = th.cmmcontainer
AND tp.parentid = th.id
JOIN basicpolicy bp ON th.systemid = bp.systemid
AND th.cmmcontainer = bp.cmmcontainer
AND th.parentid = bp.id
WHERE
(CASE
WHEN pd.TransactionEffDate < pd.TransactionDate THEN pd.TransactionDate
WHEN pd.TransactionEffDate < pd.EffectiveDate THEN pd.EffectiveDate
ELSE pd.TransactionEffDate
END) > = CAST(#StartDate AS DATE)
AND (CASE
WHEN pd.TransactionEffDate < pd.TransactionDate THEN pd.TransactionDate
WHEN pd.TransactionEffDate < pd.EffectiveDate THEN pd.EffectiveDate
ELSE pd.TransactionEffDate
END) < CAST(#EndDate + 1 AS DATE)
AND (bp.carriercd = #ResEQCarrierCd
OR #ResEQCarrierCd = 'All')
GROUP BY
CASE
WHEN pd.TransactionEffDate < pd.TransactionDate THEN cast(pd.TransactionDate as DATE)
WHEN pd.TransactionEffDate < pd.EffectiveDate THEN cast(pd.EffectiveDate as DATE)
ELSE cast(pd.TransactionEffDate as date)
END
,CONVERT(VARCHAR, pd.EffectiveDate, 101)
,CONVERT(VARCHAR, pd.ExpirationDate, 101)
,CASE
WHEN LEFT(PD.POLICYNUM, 3) = 'ORV'
THEN 'Palomar Value Select OR'
WHEN LEFT(PD.POLICYNUM, 3) = 'VSE'
THEN 'Palomar Value Select CA'
WHEN LEFT(PD.POLICYNUM, 3) = 'WAV'
THEN 'Palomar Value Select WA'
ELSE 'Palomar'
END
,CASE
WHEN pd.TransactionCode = 'EN' THEN CONVERT(VARCHAR, th.TransactionEffectiveDt, 101)
ELSE ''
END
,CONVERT(VARCHAR, DATEADD(ms, -3, DATEADD(mm, DATEDIFF(m, 0, th.transactiondt) + 1, 0)), 101)
,CASE
WHEN pd.TransactionEffDate < CAST(CONVERT(VARCHAR, pd.TransactionDate, 101) AS SMALLDATETIME) THEN CONVERT(VARCHAR, pd.TransactionDate, 101)
WHEN pd.TransactionEffDate < pd.EffectiveDate THEN CONVERT(VARCHAR, pd.EffectiveDate, 101)
ELSE CONVERT(VARCHAR, pd.TransactionEffDate, 101)
END
) lc
ORDER BY lc.[Date], lc.[Carrier], lc.[Direct Ceded Written Premium]
With the parameter that I have, it would only show up until November. However, I would like it to show the whole year, up to December at in this case, even if there are no data there since I didn't pick the enddate variable to be december. I attached an example screenshot of what it should look like when exported to excel.
Just to give you an idea:
declare #tbl TABLE(ID INT IDENTITY,SomeValue VARCHAR(100),SomeDate DATE);
INSERT INTO #tbl VALUES('Some date in March',{d'2016-03-05'}),('Some date in June',{d'2016-06-30'});
WITH AllMonths AS
(
SELECT 1 AS MonthIndex
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
UNION ALL SELECT 10
UNION ALL SELECT 11
UNION ALL SELECT 12
)
SELECT MonthIndex
,t.*
FROM AllMonths
LEFT JOIN #tbl AS t ON MONTH(t.SomeDate)=MonthIndex
The result
1 NULL NULL NULL
2 NULL NULL NULL
3 1 Some date in March 2016-03-05
4 NULL NULL NULL
5 NULL NULL NULL
6 2 Some date in June 2016-06-30
7 NULL NULL NULL
8 NULL NULL NULL
9 NULL NULL NULL
10 NULL NULL NULL
11 NULL NULL NULL
12 NULL NULL NULL
There are many ways to create a tally table
CTE with ROW_NUMBER()
A list like in my example
A physical table
It is a good idea to maintain a numbers/DATE table!
In a previous answer I showed one way to create such a table.

SQL Server : CASE-WHEN returns error in select list or Not-exist block if used in both

In the below SQL Server 2008 select statement Case-When is used in 2 places, in the select list and inside NOT EXISTS: CASE-1 and CASE-2.
It works only if I comment out one of case-when statements, only if I use it only in one place: select list OR not-exist.
If it used in both places, as below, I get error:
Conversion failed when converting date and/or time from character string.
I did my research, read http://www.fmsinc.com/free/newtips/sql/sqltip10.asp, but I still can not make it work.
Please help, what is wrong with code below? Thank you
MyTable.dob is nvarchar(10)
PayrollTable.date_of_birth is varchar(10)
Both dob columns are nullable.
MyTable.dob is in format mmddyy like '010255'.
PayrollTable.date_of_birth is in format 'mm/dd/yyyy' like '01/02/1955'
Code:
SELECT
FName,
LName,
( --- CASE-1
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(a.dob,3,0,'/'),6,0,'/')) > GETDATE()
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(a.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(a.dob,3,0,'/'),6,0,'/') AS DATE), 101)
END) as dob1
FROM
MyTable a
INNER JOIN
(SELECT
FName, LName, dob,
-- StartDate source format = yyyymm - 200104 , --- result = 2001-04-01 as DATE
MAX(CAST((STUFF(StartDate,5,0,'-') + '-01') AS DATE) ) as StartDate -- original format yyyymm
FROM
MyTable
WHERE
-- mmddyy
CAST(SUBSTRING( dob, 5, 2) as INT) > 31 --yy
AND dob != '999999'
GROUP BY
FName, LName, dob --'mmddyy'
) as t ON
LTRIM(RTRIM(a.FName)) = LTRIM(RTRIM(t.FName)) AND LTRIM(RTRIM(a.LName)) = LTRIM(RTRIM(t.LName))
AND
a.dob = t.dob --'mmddyy'
AND
CAST((STUFF(a.StartDate,5,0,'-') + '-01') AS DATE) = t.StartDate
WHERE ((LTRIM(RTRIM(a.FName)) != '' and
a.FName is not null) or
( LTRIM(RTRIM(a.LName)) != '' and a.LName is not null ) )
and
NOT EXISTS ----------------------------------
-- player does NOT exist in Party DIM alerady
(
select *
from PayrollTable p --- PARTY
where
p.date_of_birth = --t.dob -- varchar(10) 1980-09-07 p.date_of_birth
( -- CASE-2
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(t.dob,3,0,'/'),6,0,'/')) > CAST(GETDATE() as DATE) --t.dob
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE), 101) --t.dob
END
)
and
p.first_name = t.FName
and
p.last_name = t.LName
)
your problem is here.
select *
from PayrollTable p --- PARTY
where
p.date_of_birth = --t.dob -- varchar(10) 1980-09-07 p.date_of_birth
( -- CASE-2
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(t.dob,3,0,'/'),6,0,'/')) > CAST(GETDATE() as DATE) --t.dob
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
-- MISSING A WHEN CONDITION HERE
THEN DATEADD(yy, -100, CAST(STUFF(STUFF('090780',3,0,'/'),6,0,'/') AS DATE))
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE), 101) --t.dob
END
)