order by clause in union statement - sql-server

I have some records coming from 4 tables and date is not the common field in all of them but I use 'as'. Now I need to order by date
select id,convert(varchar(20), SoldDate,3) as Date from sale
union
select id,convert(varchar(20), PaymentDate,3) as Date from purchase
union
select id,convert(varchar(20), PaymentClearedDate,3) as Date from payments
union
select id,convert(varchar(20), PaymentClearedDate,3) as Date from orders
order by Date desc
I need order by Date

You can use CTE or subquery :
SELECT t.*
FROM ( <Query>
) t
ORDER BY r.Date DESC;
However, i would argue on date conversations, if you want just date then use cast(SoldDate as date) & latter convert it to dd\MM\yy.
So, your updated query would be :
SELECT t.id, CONVERT(VARCHAR(10), t.[Date], 3) AS [Date]
FROM (SELECT id, CAST(SoldDate AS DATE) AS [Date]
FROM sale
UNION
SELECT id, CAST(PaymentDate AS DATE)
FROM purchase
UNION
. . .
) t
ORDER BY t.[Date] DESC;

What goes wrong with your code? You are ordering by Date there as far as I can see. If you want to order by the Dates in date order, create another column which is the date, as a date type, e.g.
select id,convert(varchar(20), SoldDate,3) as Date,SoldDate as d2 from sale
union
select id,convert(varchar(20), PaymentDate,3) as Date, PaymentDate as d2 from purchase
union
select id,convert(varchar(20), PaymentClearedDate,3) as Date, PaymentClearedDate as d2 from payments
union
select id,convert(varchar(20), PaymentClearedDate,3) as Date, PaymentClearedDate as d2 from orders
order by d2 desc
you might need to cast your dates to type date if they are stored in some other text format
e.g.
select id,convert(varchar(20), SoldDate,3) as Date,CAST(SoldDate as datetime2) as d2 from sale
union
...etc
order by d2 desc

Related

SSMS Rolling Average over Day of Week

Leadership wants to know how Teammates are performing on Mondays & Fridays in comparison to the rest of the work week. Below is a sample temp dbo of a Teammate X's daily performance over a two-month period. Each subsequent Teammate has a different starting point from whence they are measured. I initially looked at using UNBOUNDED PRECEDING in conjunction with the various start dates, but windows functions are not cooperating. Help!
CREATE TABLE #RollingAverage
(
[Date] DATE PRIMARY KEY
,[Value] INT
);
INSERT INTO #RollingAverage
SELECT '2019-01-02',626
UNION ALL SELECT '2019-01-03',231 UNION ALL SELECT '2019-01-04',572
UNION ALL SELECT '2019-01-07',775 UNION ALL SELECT '2019-01-09',660
UNION ALL SELECT '2019-01-10',662 UNION ALL SELECT '2019-01-11',541
UNION ALL SELECT '2019-01-14',849 UNION ALL SELECT '2019-01-15',632
UNION ALL SELECT '2019-01-16',906 UNION ALL SELECT '2019-01-18',961
UNION ALL SELECT '2019-01-21',501 UNION ALL SELECT '2019-01-24',311
UNION ALL SELECT '2019-01-25',614 UNION ALL SELECT '2019-01-28',296
UNION ALL SELECT '2019-01-29',390 UNION ALL SELECT '2019-01-31',804
UNION ALL SELECT '2019-02-01',928 UNION ALL SELECT '2019-02-05',855
UNION ALL SELECT '2019-02-06',605 UNION ALL SELECT '2019-02-08',283
UNION ALL SELECT '2019-02-12',144 UNION ALL SELECT '2019-02-14',382
UNION ALL SELECT '2019-02-15',862 UNION ALL SELECT '2019-02-18',549
UNION ALL SELECT '2019-02-19',401 UNION ALL SELECT '2019-02-20',515
UNION ALL SELECT '2019-02-21',590 UNION ALL SELECT '2019-02-22',625
UNION ALL SELECT '2019-02-25',304 UNION ALL SELECT '2019-02-26',402
UNION ALL SELECT '2019-02-27',326;
AVG(Value) over (ORDER BY [Date] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) did not work
The first thing you need to understand, is that your "daily" performance is not daily. A simple solution would be to fill the gaps to be able to effectively count the days.
I filled the gaps using a CTE that generates a calendar table on the fly, but you could use a permanent calendar table if available.
WITH
E(n) AS(
SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
SELECT a.n FROM E a, E b
),
cteCalendar(calDate) AS(
SELECT TOP (61)
CAST( DATEADD( DD, 1-ROW_NUMBER() OVER(ORDER BY (SELECT NULL)), GETDATE()) AS date) AS calDate
FROM E2
),
cteRollingAverages AS(
SELECT ra.[Date],
ra.value,
AVG(Value) over (ORDER BY calDate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) RollingAverage
FROM #RollingAverage AS ra
RIGHT JOIN cteCalendar AS c ON ra.[Date] = c.calDate
)
SELECT *
FROM cteRollingAverages
WHERE [Date] IS NOT NULL
ORDER BY [Date];
A different option is to use APPLY. This is not limited by a certain date.
SELECT *
FROM #RollingAverage r
CROSS APPLY( SELECT AVG(i.[Value]) AS RollingAvg
FROM #RollingAverage i
WHERE i.[Date] BETWEEN DATEADD( DD, -7, r.[Date]) AND r.[Date]) av
ORDER BY [Date];

Distinct columns should have one date per month in SQL Server

My table has columns Name, EmpName, Date. For distinct Name and EmpName values, Date should be only one value per month
For example:
Name EmpName Date
-----------------------
abc emp1 3/19/2018
abc emp1 3/22/2018 (This record should be rejected)
xyz emp2 3/15/2018 valid record
I wrote something like this
SELECT
name, empname,
ROW_NUMBER() OVER (PARTITION BY YEAR(date), MONTH(date) ORDER BY date DESC)
I got stuck writing a CASE statement
You can use row_number() :
select top (1) with ties t.*
from table t
order by row_number() over (partition by name, empname, year(date), month(date) order by date);
However, based on sample data simple aggregation would also work :
select name, empname, min(date)
from table t
group by name, empname, year(date), month(date);

selecting some data within specific number of days

I'm working on sales data and I want to know if Customer A purchased product X from more than one provider within 3 days and I'm working on only one date Claim Date
I Can't find T-Sql query for it
for example
SELECT CusName,ProdName,ProvName
FROM table1
WHERE [Claim Date] between Day([Claim Date]) and DATEADD (Day ,-3 , [Claim Date]
A WHERE EXISTS clause should do the job:
SELECT CusName,ProdName,ProvName
FROM table1 a
WHERE EXISTS (
SELECT 1 FROM table1 b WHERE
b.CusName=a.CusName AND
b.ProdName=a.ProdName AND
b.ProvName!=a.ProvName AND
ABS(DATEDIFF(day,a.ClaimDate,b.ClaimDate))<3
)
You can use the below code for that
SELECT t1.CusName,t1.ProdName,t1.ProvName,t2.ProvName
FROM table t1
JOIN table t2 ON t1.CusName=t2.CusName AND t1.ProdName=t2.ProdName
WHERE t1.ProvName!=t2.ProvName
AND ABS(DATEDIFF(day,t1.ClaimDate,t2.ClaimDate)) = 3
You need a having clause and a count of the providers:
SELECT CusName, COUNT(DISTINCT ProvName) Provider_count
FROM table1
WHERE [Claim Date] between Day([Claim Date]) and DATEADD (Day ,-3 , [Claim Date]
AND ProdName = 'X'
GROUP BY CusName
HAVING COUNT(DISTINCT ProvName) > 1
Note, you do not need to include the count in the select clause, but you do need it in the having clause.

I am trying to assign the month wise leaves in an year to my database(sql server) but it fails. below is the code I have tried

i trying to assign the month wise leaves in year in my database(sql server) but its fail below my trying code is there
select count(*)(SELECT DATEPART(yyyy,Date) AS OrderYear,
DATEPART(mm,Date) AS OrderMonth,
DATEPART(dd,Date) AS OrderDay
FROM Leaves
WHERE EmployeeID=37) FROM Leaves where OrderYear = '2016'
This below code will do what you need to do. Just had to make some small changes to your above code:
you will need an inner query which will extract the date parts, which will then need to be selected.
An outer query will need to then select from the inner query and filter on the new date part field.
Here is how I would do it:
select
count(*)
FROM
(
SELECT
DATEPART(yyyy, Date) AS OrderYear,
DATEPART(mm, Date) AS OrderMonth,
DATEPART(dd, Date) AS OrderDay
FROM
Leaves
WHERE
EmployeeID = 37
) A
WHERE
OrderYear = '2016';
You may looking for this :
;WITH CTE AS(
SELECT 1 as MonthNumber
UNION ALL
SELECT MonthNumber+1 AS MonthNumber
FROM CTE
WHERE MonthNumber<=12
)
SELECT MonthNumber,COUNT(*)
FROM CTE
LEFT JOIN Leaves ON MONTH(DATE) = MonthNumber AND EmployeeID=37 AND YEAR(Date)=2016
GROUP BY MonthNumber

Group By Month and Year to get distinct month and years then combine as a single date SQL

SELECT CONVERT(DATE,CAST([Year] AS VARCHAR(4))+'-'+
CAST([Month] AS VARCHAR(2))+'-'+
CAST('1' AS VARCHAR(2))) Date
FROM (SELECT YEAR(Date) as [Year], MONTH(Date) as [Month] FROM [dbo].[Data]
GROUP BY YEAR(Date), MONTH(Date)) x
ORDER BY Date DESC
Is there a better way to doinq this with a single query?
The query should return the unique month and year from a table but as combined Date.
IF OBJECT_ID ('tempdb..#TempT') IS NOT NULL DROP TABLE #TempT
CREATE TABLE #TempT(
dt datetime)
INSERT INTO #TempT (dt) VALUES
('2016-10-11'),
('2016-10-3'),
('2016-9-13'),
('2016-9-16')
SELECT DISTINCT CAST(DATEADD(month, DATEDIFF(month, 0, dt), 0) as DATE) AS Dates
from #TempT
Sample data is really a necessity for these kinds of questions, but this function could also be a help for you DATEFROMPARTS
SELECT
DATEFROMPARTS([Year], [Month], 01)
FROM
(
SELECT
YEAR(Date) as [Year],
MONTH(Date) as [Month]
FROM [dbo].[Data]
GROUP BY YEAR(Date), MONTH(Date)
) x
ORDER BY Date DESC
This code takes whatever date you enter and evaluates it as the first of the month. Effectively looking at only month and year:
SELECT
DATEADD(MM,DATEDIFF(MM,0, [Date] ),0) AS [YearMonth]
FROM [dbo].[Data]
ORDER BY
DATEADD(MM,DATEDIFF(MM,0, [Date] ),0)
;

Resources