Reading the day for the current month SQL - c#

This is my current query that works, but I still need days to print out for the whole month starting 2018-05-01, not to skip, is this possible in a sql?
DECLARE #MinDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) ,
#MaxDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1);
SELECT TOP (DATEDIFF(DAY, #MinDate, #MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, #MinDate) INTO #MYCALENDAR FROM sys.all_objects a CROSS JOIN sys.all_objects b;
SELECT
a.LPE_Pensum,
DATEPART(DAY, CAL.[Date]) AS Tag ,
LEFT(datename(WEEKDAY, CAL.[Date] ),3) AS Datum,
CAL.[Date],
p.ZPZ_Von,
p.ZPZ_Bis FROM
#MYCALENDAR CAL
LEFT JOIN Z_PRAESENZZEIT AS p ON CONVERT(DATE, p.ZPZ_Datum) = CONVERT(DATE, CAL.[Date])
LEFT JOIN A_PERSONAL AS a ON a.LPE_ID = p.ZPZ_LPE_ID
LEFT JOIN A_Arbeitszeitplan AS r on r.LPE_AbteilungID = a.LPE_AbteilungID
LEFT JOIN A_Abteilung AS b ON b.LPE_AbteilungID = r.LPE_AbteilungID WHERE a.LPE_ID=13
and this is the result of a query:
enter image description here
Thanks for your help

You want to scan a particular range of dates, lets say previous month:
DECLARE #MinDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) , -1st day prev month
#MaxDate DATE = DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1); -- last day prev month
Now what you need is a calendar table to store your dates:
SELECT TOP (DATEDIFF(DAY, #MinDate, #MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, #MinDate)
INTO #MYCALENDAR
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
We can use our new #MYCALENDAR as baseline for our query:
SELECT
a.LPE_Pensum,
DATEPART(DAY, CAL.[Date]) AS Tag ,
LEFT(datename(WEEKDAY, CAL.[Date] ),3) AS Datum,
CAL.[Date],
p.ZPZ_Von,
p.ZPZ_Bis
FROM
#MYCALENDAR CAL
LEFT JOIN Z_PRAESENZZEIT AS p ON CONVERT(DATE, p.ZPZ_Datum) = CONVERT(DATE, CAL.[Date])
LEFT JOIN A_PERSONAL AS a ON a.LPE_ID = p.ZPZ_LPE_ID
LEFT JOIN A_Arbeitszeitplan AS r on r.LPE_AbteilungID = a.LPE_AbteilungID
LEFT JOIN A_Abteilung AS b ON b.LPE_AbteilungID = r.LPE_AbteilungID
WHERE
a.LPE_ID=13
you may have to change something in your join clauses but, basically, this is how i would proceed.

First of all, try to indent your query, it's impossible to read it that way. Second, you can create a dates table with all the days you are interested in. Search in internet for date dimensions, they will fit very well with your need. And finally, you must left join your query with this table, in order to have a way to see all the days not present in your data.
It would be something like this:
SELECT
a.LPE_Pensum,
dd.[DAY] AS Tag ,
LEFT(datename(WEEKDAY, p.ZPZ_Datum ),3) AS Datum,
p.ZPZ_Datum,p.ZPZ_Von,
p.ZPZ_Bis
FROM [DATE_DIM] dd
LEFT JOIN Z_PRAESENZZEIT AS p
ON dd.[DATE]=DATEPART(DAY, p.ZPZ_Datum)
LEFT JOIN A_PERSONAL AS a
ON a.LPE_ID = p.ZPZ_LPE_ID
AND a.LPE_ID=13
LEFT JOIN A_Arbeitszeitplan AS r
on r.LPE_AbteilungID = a.LPE_AbteilungID
LEFT JOIN A_Abteilung AS b
ON b.LPE_AbteilungID = r.LPE_AbteilungID
WHERE dd.[YEAR]=#YearInterestedIn
The dd.[YEAR]=#YearInterestedIn must be replaced by the range you are interested in your study

You need to generate the days for the current month. Assuming you have some rows in your database, then you can use left join to bring in the dates:
SELECT a.LPE_Pensum, d.dte AS Tag ,
LEFT(datename(WEEKDAY, d.dte),3) AS Datum,
p.ZPZ_Datum, p.ZPZ_Von, p.ZPZ_Bis
FROM (SELECT DISTINCT CAST(p.ZPZ_Datum as date) as dte
FROM Z_PRAESENZZEIT p
WHERE ZPZ_Datum >= datefromparts(year(p.ZPZ_Datum), month(p.ZPZ_Datum), 1) AND
ZPZ_Datum >= dateadd(month, 1, datefromparts(year(p.ZPZ_Datum), month(p.ZPZ_Datum), 1))
) d LEFT JOIN
(A_PERSONAL a JOIN
Z_PRAESENZZEIT p
ON a.LPE_ID = p.ZPZ_LPE_ID
)
ON p.ZPZ_Datum >= d.dte AND p.ZPZ_Datum < DATEADD(day, 1, d.dte) LEFT JOIN
A_Arbeitszeitplan r
ON r.LPE_AbteilungID = a.LPE_AbteilungID
A_Abteilung b
ON b.LPE_AbteilungID = r.LPE_AbteilungID
WHERE a.LPE_ID = 13;
You can generate the dates in a different fashion if necessary.

Related

How to show two pieces of data in one row depend on id in rdlc reporting

Blue is one employee name and red is another employee name. Here showing two rows but I want one row. I'm using
=Fields!EmpName.Value & Fields!LeaveDate.Value
expression how to show two rows of data into one row. That means blue row contains two leave types in one row
Used each row =Fields!EmpName.Value & Fields!LeaveDate.Value expression
CREATE PROCEDURE query
(#EmployeeIds varchar(8000),
#TenantId int)
AS
BEGIN
DECLARE #empIds TABLE (id int);
INSERT INTO #empIds
SELECT Id
FROM SplitStringToIntRows(#EmployeeIds, ',');
SELECT
et.LeaveDate AS LeaveDate, lt.Value AS LeaveType,
emp.FirstName + ' ' + emp.LastName AS EmpName,
emp.CustomEmployeeId AS CustomEmployeeId,
CONVERT(DATE, GETDATE()) AS StartDate,
DATEADD(month, 1, CONVERT (date, GETDATE())) AS EndDate
FROM
LeaveManagement.EmployeeLeaveTransaction et
INNER JOIN
LeaveManagement.LeaveMaster lm ON et.LeaveMasterId = lm.LeaveMasterId
INNER JOIN
Lookup.LeaveType lt ON lt.LeaveTypeId = lm.LeaveTypeId
INNER JOIN
HumanResource.Employee emp ON emp.EmployeeId = et.EmployeeId
INNER JOIN
#empIds empPar ON empPar.id = et.EmployeeId
WHERE
CONVERT(DATETIME, CAST(et.LeaveDate AS DATE), 110) >= CONVERT(DATE, GETDATE())
AND CONVERT(DATETIME, CAST(et.LeaveDate AS DATE), 110) <= DATEADD(month, 1, CONVERT (date, GETDATE()))
AND emp.TenantId = #TenantId
--AND lt.Value='No Pay Leave'
END
you must add "Fields!EmpName.Value " in the Group expressions of the row groups.
add EmpName field into your row groups. e.g. in below image i have grouped my data in HRIM field that i had.

Output transactions that exceed certain amount within 3 days

In a month, seperate by AccountNo, all transaction that exceeds 10,000 amount within 3 days must be outputted.
This is a sample table:
AccountNo-----Date------------Amount
1-------------5/1/17----------8000
1-------------5/3/17----------1000
1-------------5/4/17----------1000
1-------------5/6/17----------1000
2-------------5/7/17----------3000
2-------------5/10/17---------2000
2-------------5/13/17---------2000
2-------------5/13/17---------3000
3-------------5/14/17---------3000
3-------------5/15/17---------3000
3-------------5/16/17---------9000
4-------------5/17/17---------1000
5-------------5/18/17---------1000
5-------------5/19/17---------1000
5-------------5/20/17---------1000
The result must be:
AccountNo-----Date------------Amount
1-------------5/1/17----------8000
1-------------5/3/17----------1000
1-------------5/4/17----------1000
2-------------5/7/17----------3000
2-------------5/10/17---------2000
2-------------5/13/17---------2000
2-------------5/13/17---------3000
3-------------5/14/17---------3000
3-------------5/15/17---------3000
3-------------5/16/17---------9000
There is a code given to me, but it's not completely working yet.
Select A.*
From YourTable A
Cross Apply (
Select RT1 = sum(case when [Date] <= B2.TstDate then [Amount] else 0 end)
,RT2 = sum(case when [Date] >= B2.TstDate then [Amount] else 0 end)
From YourTable B1
Cross Join (Select TstDate=A.[Date]) B2
Where [Date] between DateAdd(DAY,-2,A.[Date]) and DateAdd(DAY,2,A.[Date])
and Year([Date])=Year(TstDate)
and Month([Date])=Month(TstDate)
) B
Where RT1>=10000 or RT2>=10000
Common table expression: TransInfo
TransInfo is a table with account, year, month, day, amount
The main query:
The [Tmiddle] query adds a row_number based on amount per day per month per accountno
The [Tmiddle] is joined again with TransInfo to limit the results to top 3 of a month AS [Touter] where the top 3 is >= 10.000
The outer most query combines the result with a table again to gain the complete transaction information again
In short:
Filter data on top 3 amounts per day per month per year per account
Check if sum of amount >= 10.000
Show results
Query:
WITH [TransInfo] ([AccountNo], [Year], [Month], [Day], [Amount], [Rownumber])
AS
(
SELECT [AccountNo]
,[Year]
,[Month]
,[Day]
,[Amount]
,ROW_NUMBER() OVER
(
PARTITION BY [AccountNo],
[Year],
[Month]
ORDER BY [Amount] DESC
) AS [Rownumber]
FROM
(
SELECT [AccountNo]
,DATEPART(YEAR, [Date]) AS [Year]
,DATEPART(MONTH, [Date]) AS [Month]
,DATEPART(DAY, [Date]) AS [Day]
,SUM([Amount]) AS [Amount]
FROM [Test].[dbo].[Data]
GROUP BY [AccountNo],
DATEPART(MONTH, [Date]),
DATEPART(YEAR, [Date]),
DATEPART(DAY, [Date])
) AS [Tinner]
)
SELECT [Data].[AccountNo]
,[Data].[Date]
,[Data].[Amount]
FROM [Test].[dbo].[Data]
INNER JOIN
(
SELECT [TransInfo].[AccountNo]
,[TransInfo].[Year]
,[TransInfo].[Month]
,[TransInfo].[Day]
,[TransInfo].[Amount]
FROM [TransInfo]
INNER JOIN
(
SELECT [AccountNo]
,[Year]
,[Month]
FROM [TransInfo]
WHERE [TransInfo].[Rownumber] <= 3
GROUP BY [TransInfo].[AccountNo],
[TransInfo].[Year],
[TransInfo].[Month]
HAVING SUM ([TransInfo].[Amount]) >= 10000
) AS [Tmiddle]
ON [Tmiddle].[AccountNo] = [TransInfo].[AccountNo]
AND [Tmiddle].[Year] = [TransInfo].[Year]
AND [Tmiddle].[Month] = [TransInfo].[Month]
WHERE [TransInfo].[Rownumber] <= 3
) AS [Touter]
ON [Data].[AccountNo] = [TOuter].[AccountNo]
AND DATEPART(YEAR, [Data].[Date]) = [TOuter].[Year]
AND DATEPART(MONTH, [Data].[Date]) = [TOuter].[Month]
AND DATEPART(DAY, [Data].[Date]) = [TOuter].[Day]
Result: Left is query result, right is complete table
Does this work as expected? You may need to change the 2's to 3's depending on what you mean by 'within 3 days'.
SELECT DISTINCT C.*
FROM YourTable C
INNER JOIN (
SELECT a.AccountNo, a.Date
FROM YourTable a
INNER JOIN YourTable b
ON a.AccountNo = b.AccountNo
AND DATEADD(DAY, 2, a.Date) <= b.Date AND b.Date >= a.Date
GROUP BY a.AccountNo, a.Date
HAVING SUM(b.Amount) > 10000
) d
ON C.AccountNo = d.AccountNo
AND DATEADD(DAY, 2, D.Date) <= C.Date AND C.Date >= D.Date

Issue With Select Statement

I am trying to select the top 1 of this select query then order DESC, every way I try, it doesn't seem to work. Here is my code:
SELECT '$' + CONVERT(VARCHAR(50),
CONVERT(MONEY, COALESCE(([amount]), 0)),
1) AS [Total]
FROM [myTable] a
left join [mySecondTable] b on a.[ID] = b.[ID]
left join [myThirdTable c on c.[myNumber] = b.[myNumber]
WHERE c.[myName] = 'me'
If I wanted to select top 1 amount and then order by amount with SELECT TOP 1 and ORDER By [amount] DESC, where would I put them exactly? Or this that even the correct way to do this?
Your ORDER BY will go at the end, and top 1 at the beginning.
SELECT top 1 '$' + CONVERT(VARCHAR(50),
CONVERT(MONEY, COALESCE(SUM([amount]), 0)),
1) AS [Total]
FROM [myTable] a
left join [mySecondTable] b on a.[ID] = b.[ID]
left join [myThirdTable c on c.[myNumber] = b.[myNumber]
WHERE c.[myName] = 'me'
order by [AMOUNT] DESC

Could this be converted to LINQ?

I have a reasonably long SQL query that I need to run in a .Net application. I can make it a stored procedure but I'd like to avoid it if possible (given that I may have a high number of queries in this app).
With this in mind, could something like the following be converted to LINQ or is it too detailed?
-- Compare current period to historical data
select Name ,
avg(TimeProcessing + TimeRendering + TimeDataRetrieval) / 1000 as 'Current Month' ,
isnull(count(TimeProcessing), 0) as 'Sample' ,
min(l2.[Avg_Exec_Time_Previous_Month]) as 'Previous Month' ,
isnull(min(l2.[Executions_Last_Month]), 0) as 'Sample' ,
min(l3.[Avg_Exec_Time_Two_Months_Ago]) as 'Two Months ago' ,
isnull(min(l3.[Executions_Two_Months_Ago]), 0) as 'Sample'
from marlin.report_execution_log l
inner join marlin.report_catalog c on l.ReportID = c.ItemID
left outer join (
select
l2.ReportID ,
(
avg(l2.TimeProcessing + l2.TimeRendering
+ l2.TimeDataRetrieval) / 1000
) as 'Avg_Exec_Time_Previous_Month' ,
count(l2.TimeProcessing) as 'Executions_Last_Month'
from
marlin.report_execution_log l2
where
TimeEnd between dateadd(MONTH, -2, getdate())
and dateadd(MONTH, -1, getdate())
group by
l2.ReportID
) l2 on l.ReportID = l2.ReportID
left outer join (
select
l3.ReportID ,
(
avg(l3.TimeProcessing + l3.TimeRendering + l3.TimeDataRetrieval) / 1000
) as 'Avg_Exec_Time_Two_Months_Ago' ,
count(l3.TimeProcessing) as 'Executions_Two_Months_Ago'
from
marlin.report_execution_log l3
where
TimeEnd between dateadd(MONTH, -3, getdate())
and dateadd(MONTH, -2, getdate())
group by
l3.ReportID
) l3 on l.ReportID = l3.ReportID
group by l.ReportID ,
Name
order by 2 desc
there are many tools /convertor are available on the internet. you can use this tools
why not you try Sql to Linq
LinqPad

Querying in advance with linq2sql for data with gaps

Hi i have table: Values with ValueId, Timestamp , Value and BelongTo. Each 15 minutes there is insreted new row into that table with new value, current timestamp and specific BelongTo field. And now i want to find gaps i mean values where one after another has timestamp more then 15 minutes.
I was trying this:
var gaps = from p1 in db.T_Values
join p2 in db.T_Values on p1.TimeStamp.AddMinutes(15) equals p2.TimeStamp
into grups where !grups.Any() select new {p1};
and it works but i don't know if this is optimall, what do you think? and i don't know how can i add where p1.BelongTo == 1. Cos this query looks for all data.
Jon told
var gaps = from p1 in db.T_Values
where p1.BelongTo == 1
where !db.T_Values.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
select p1;
Jon this last query is translated to:
exec sp_executesql N'SELECT [t0].[ValueID], [t0].[TimeStamp], [t0].[Value],
[t0].[BelongTo], [t0].[Type]
FROM [dbo].[T_Values] AS [t0]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(ms, (CONVERT(BigInt,#p0 * 60000)) % 86400000,
DATEADD(day, (CONVERT(BigInt,#p0 * 60000)) / 86400000, [t0].[TimeStamp])) = [t1].[TimeStamp]
))) AND ([t0].[BelongTo] = #p1)',N'#p0 float,#p1 int',#p0=15,#p1=1
and it works unless all rows have the same belongTo, when there are rows with BelongTo with many diferent values then i've noticed I need to add to sql:and [t1].BelongTo = 1 which should finally look like this
N'SELECT [t0].[ValueID], [t0].[TimeStamp], [t0].[Value], [t0].[BelongTo], [t0].[Type]
FROM [dbo].[T_Values] AS [t0]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(ms, (CONVERT(BigInt,#p0 * 60000)) % 86400000,
DATEADD(day, (CONVERT(BigInt,#p0 * 60000)) / 86400000, [t0].[TimeStamp])) = [t1].[TimeStamp]
and [t1].BelongTo = 1
))) AND ([t0].[BelongTo] = #p1)',N'#p0 float,#p1 int',#p0=15,#p1=1
other words:
SELECT TimeStamp
FROM [dbo].[T_Values] AS [t0]
WHERE NOT( (EXISTS (SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(MINUTE, 15, [t0].[TimeStamp]) = [t1].[TimeStamp])))
AND ([t0].[BelongTo] = 1)
shoud change to
SELECT TimeStamp
FROM [dbo].[T_Values] AS [t0]
WHERE NOT( (EXISTS (SELECT NULL AS [EMPTY]
FROM [dbo].[T_Values] AS [t1]
WHERE DATEADD(MINUTE, 15, [t0].[TimeStamp]) = [t1].[TimeStamp] and [t1].BelongTo=1)))
AND ([t0].[BelongTo] = 1)
but I am still thinking how can I add this to linkq
Well adding the extra where clause is easy (and I'll remove the pointless anonymous type at the same time):
var gaps = from p1 in db.T_Values
where p1.BelongTo == 1
join p2 in db.T_Values
on p1.TimeStamp.AddMinutes(15) equals p2.TimeStamp
into grups
where !grups.Any()
select p1;
I'm not sure why you're grouping though... I would have thought this would be simpler:
var gaps = from p1 in db.T_Values
where p1.BelongTo == 1
where !db.T_Values.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
select p1;
As for performance - look at the generated SQL and how it looks in SQL profiler.
EDIT: If you need the BelongTo check in both versions (makes sense) I'd suggest this:
var sequence = db.T_Values.Where(p => p.BelongTo == 1);
var gaps = from p1 in sequence
where !sequence.Any(p2 => p1.TimeStamp.AddMinutes(15) == p2.Timestamp)
select p1;
How about
var gaps = dbT_Values.Take(dbT_Values.Count()-1)
.Select((p, index) => new {P1 = p, P2 = dbT_Values.ElementAt(index + 1)})
.Where(p => p.P1.BelongsTo == 1 && p.P1.TimeStamp.AddMinutes(15).Equals(p.P2.TimeStamp)).Select(p => p.P1);

Categories

Resources