I have a thousand of records in one column and I want to cross join with date range let’s say between ‘2022-01-01 and ‘2022-02-15’. I don’t know how to start with sql server query, anyone can help?
Here’s my data (only one column)
City
Los Angeles
New York
Miami
Berlin
Dublin
Bologna
Desired result: (I shown 2 examples each only but the actual results should be 276 records)
Angeles/Dte-01Jan22
Los Angeles/Dte-02Jan22
New York/Dte-01Jan22
New York/Dte-02Jan22
Miami/Dte-01Jan22
Miami/Dte-02Jan22
Berlin/Dte-01Jan22
Berlin/Dte-02Jan22
Dublin/Dte-01Jan22
Dublin/Dte-02Jan22
Bologna/Dte-01Jan22
Bologna/Dte-02Jan22
You can do:
with
p (ds, de) as (
select convert(date, '20220101', 112), -- start date
convert(date, '20220215', 112) -- end date
),
r as (
select ds as d from p
union all
select dateadd(day, 1, r.d) from r join p on r.d < p.de
)
select concat(t.city, '/Dte', format(r.d, 'ddMMMyy'))
from r
cross join t
See running example at db<>fiddle.
This is how I understood the question, you should use this query:
SELECT * FROM dbo.Cities AS C
JOIN dbo.Dates AS D
WHERE D.Date BETWEEN '2022-01-01' AND '2022-01-30'
ORDER BY C.Name,D.Date
You can use CROSS APPLY on another queries :) JOINs have better performance on your data.
Related
I don't know exactly where I'm wrong, but I need a list of all the workers who are currently at work (for the current day), this is my sql query:
SELECT
zp.ID,
zp.USER_ID,
zp.Arrive,
zp.Deppart,
zp.DATUM
FROM time_recording as zp
INNER JOIN personal AS a on zp.USER_ID, = zp.USER_ID,
WHERE zp.Arrive IS NOT NULL
AND zp.Deppart IS NULL
AND zp.DATUM = convert(date, getdate())
ORDER BY zp.ID DESC
this is what the data looks like with my query:
For me the question is, how can I correct my query so that I only get the last Arrive time for the current day for each user?
In this case to get only these values:
Try this below script using ROW_NUMBER as below-
SELECT * FROM
(
SELECT zp.ID, zp.USER_ID, zp.Arrive, zp.Deppart, zp.DATUM,
ROW_NMBER() OVER(PARTITION BY zp.User_id ORDER BY zp.Arrive DESC) RN
FROM time_recording as zp
INNER JOIN personal AS a
on zp.USER_ID = zp.USER_ID
-- You need to adjust above join relation as both goes to same table
-- In addition, as you are selecting nothing from table personal, you can drop the total JOIN part
WHERE zp.Arrive IS NOT NULL
AND zp.Deppart IS NULL
AND zp.DATUM = convert(date, getdate())
)A
WHERE RN =1
you can try this:
SELECT DISTINCT
USER_ID,
LAR.LastArrive
FROM time_recording as tr
CROSS APPLY (
SELECT
MAX(Arrive) as LastArrive
FROM time_recording as ta
WHERE
tr.USER_ID = ta.USER_ID AND
ta.Arrive IS NOT NULL
) as LAR
I have made a view in order to analyze a specific subject with PowerBI(I can't use other program). In My case the dataBase is according to the following ERD:
The ERD
I've created the following view:
CREATE VIEW sales_based_foodstyless AS
(
SELECT food_style,
total_quantities=Sum(quantity),
average_dish_price=Avg(d.price),
total _revenue=sum(quantity*price),
orders_amount=count(DISTINCT o.orderid),
total_vendors_operating=count( v.vendorid)
FROM vendors AS v
JOIN food_style AS fs
ON fs.vendorid=v.vendorid
JOIN dishes AS d
ON v.vendorid=d.vendorid
JOIN dish_quantities AS dq
ON d.vendorid=dq.vendorid
JOIN orders AS o
ON dq.orderid=o.orderid
GROUP BY food_style
)
I want in the PowerBI to filter the data by date which is to be found as Order_Date of the joined table in the select statement of the view. however I cannot managed to do it.
Help Please
You can add a filter for example
CREATE VIEW sales_based_foodstyless AS
(
SELECT
food_style,
total_quantities=Sum(quantity),
average_dish_price=Avg(d.price),
total _revenue=sum(quantity*price),
orders_amount=count(DISTINCT o.orderid),
total_vendors_operating=count( v.vendorid)
FROM vendors AS v
JOIN food_style AS fs ON fs.vendorid=v.vendorid
JOIN dishes AS d ON v.vendorid=d.vendorid
JOIN dish_quantities AS dq ON d.vendorid=dq.vendorid
JOIN orders AS o ON dq.orderid=o.orderid
WHERE YEAR(order_date) = 2018
GROUP BY food_style
)
However, if you want to do this dynamically you would have to use a stored procedure or parameterized view.
You can do this with a table-valued function:
CREATE FUNCTION fSelectSalesBasedFoodstyles (
#StartDate DATE
, #EndDate DATE
)
RETURNS TABLE
AS
RETURN
SELECT food_style,
total_quantities=Sum(quantity),
average_dish_price=Avg(d.price),
total _revenue=sum(quantity*price),
orders_amount=count(DISTINCT o.orderid),
total_vendors_operating=count( v.vendorid) ,
order_date
FROM vendors AS v
JOIN food_style AS fs
ON fs.vendorid=v.vendorid
JOIN dishes AS d
ON v.vendorid=d.vendorid
JOIN dish_quantities AS dq
ON d.vendorid=dq.vendorid
JOIN orders AS o
ON dq.orderid=o.orderid
-- CAST only necessary if OrderDate is a DATETIME:
WHERE CAST(o.order_date AS DATE) >= #StartDate
AND CAST(o.order_date AS DATE) <= #EndDate
GROUP BY food_style
GO
I am relatively new at SQL so I apologise if this is obvious but I cannot work out how to use the results of the WITH clause query in the where statement of my main query.
My with query pulls the first record for each customer and gives the sale date for that record:
WITH summary AS(
SELECT ed2.customer,ed2.saledate,
ROW_NUMBER()OVER(PARTITION BY ed2.customer
ORDER BY ed2.saledate)AS rk
FROM Filteredxportdocument ed2)
SELECT s.*
FROM summary s
WHERE s.rk=1
I need to use the date in the above query as the starting point and pull all records for each customer for their first 12 months i.e. where the sale date is between ed2.saledate AND ed2.saledate+12 months.
My main query is:
SELECT ed.totalamountincvat, ed.saledate, ed.name AS SaleRef,
ed.customer, ed.customername, comp.numberofemployees,
comp.companyuid
FROM exportdocument AS ed INNER JOIN
FilteredAccount AS comp ON ed.customer = comp.accountid
WHERE (ed.statecode = 0) AND
ed.saledate BETWEEN ed2.saledate AND DATEADD(M,12,ed2.saledate)
I am sure that I need to add the main query into the WITH clause but I cant work out where. Is anyone able to help please
Does this help?
;WITH summary AS(
SELECT ed2.customer,ed2.saledate,
ROW_NUMBER()OVER(PARTITION BY ed2.customer
ORDER BY ed2.saledate)AS rk
FROM Filteredxportdocument ed2)
SELECT ed.totalamountincvat, ed.saledate, ed.name AS SaleRef,
ed.customer, ed.customername, comp.numberofemployees,
comp.companyuid
FROM exportdocument AS ed INNER JOIN
FilteredAccount AS comp ON ed.customer = comp.accountid
OUTER APPLY (SELECT s.* FROM summary s WHERE s.rk=1) ed2
WHERE ed.statecode = 0 AND
ed.saledate BETWEEN ed2.saledate AND DATEADD(M,12,ed2.saledate)
and ed.Customer = ed2.Customer
Results of CTE are not cached or stored, so you can't reuse it.
EDIT:
Based upon your requirement that all the records from CTE should be in final result, this is a new query:
;WITH summary AS(
SELECT ed2.customer,ed2.saledate,
ROW_NUMBER()OVER(PARTITION BY ed2.customer
ORDER BY ed2.saledate)AS rk
FROM Filteredxportdocument ed2)
SELECT
ed.totalamountincvat,
ed.saledate,
ed.name AS SaleRef,
ed.customer,
ed.customername,
comp.numberofemployees,
comp.companyuid
FROM
summary ed2
left join exportdocument ed
on ed.Customer = ed2.Customer
and ed.statecode = 0
AND ed.saledate BETWEEN ed2.saledate AND DATEADD(M,12,ed2.saledate)
INNER JOIN FilteredAccount comp
ON ed.customer = comp.accountid
WHERE
s.rk=1
summary you will be able to use only once. Alternate solution is store summary into temp table and use that as many times as u want.
Something like : Select * into #temp from Summary s where s.rk=1
I have 3 tables that are joined together with this query.
One of them brings me people names , another one brings me their points and the last one brings me date time.
I select the total people score.
Also, there is a column in the 3th tables that brings me the scores' transaction Date Time. My problem is that I want to write a TSQL query with this condition:
Select the transaction date where the people score is 12,000 or more.
In my idea I should use while loop but I do not know the syntax?
This is how I would do it-
SELECT cp.FirstName
, cp.LastName
, SUM(Points) as Score
FROM ClubProfile cp
RIGHT JOIN CardTransaction ct
ON cp.ClubProfileId = ct.ClubProfileId
INNER JOIN Your3rdTable as t3
ON cp.ClubProfileId = t3.ClubProfileId
WHERE CONVERT(VARCHAR, ct.[Date Column], 101) = #your_date_param
GROUP BY
cp.FirstName
, cp.LastName
HAVING SUM(Points) >=12000
Based on your post this should be close to what you need. You need to add that 3rd table and alter this statement accordingly.
SELECT cp.FirstName
, cp.LastName
, SUM(Points) as Score
FROM [fidilio].[dbo].[ClubProfile] cp
RIGHT JOIN (
CardTransaction ct
INNER JOIN CardTransactionLog ctl
ON cp.CardTransactionLogId = ctl.CardTransactionLogId
)
ON cp.ClubProfileId = ct.ClubProfileId
GROUP BY
cp.FirstName
, cp.LastName
HAVING SUM(Points) >=12000
AND ctl.TransactionTimeStamp = #SomeDateTimeVariable
The variable #SomeDateTimeVariable has to come from someplace what is your exact time-frame criteria
I have a history table containing a snapshot of each time a record is changed. I'm trying to return a certain history row with the original captured date. I am currently using this at the moment:
select
s.Description,
h.CaptureDate OriginalCaptureDate
from
HistoryStock s
left join
( select
StockId,
CaptureDate
from
HistoryStock
where
HistoryStockId in ( select MIN(HistoryStockId) from HistoryStock group by StockId )
) h on s.StockId = h.StockId
where
s.HistoryStockId = #HistoryStockId
This works but with 1 Million records its on the slow side and I'm not sure how to optimize this query.
How can this query be optimized?
UPDATE:
WITH OriginalStock (StockId, HistoryStockId)
AS (
SELECT StockId, min(HistoryStockId)
from HistoryStock group by StockId
),
OriginalCaptureDate (StockId, OriginalCaptureDate)
As (
SELECT h.StockId, h.CaptureDate
from HistoryStock h join OriginalStock o on h.HistoryStockId = o.HistoryStockId
)
select
s.Description,
h.OriginalCaptureDate
from
HistoryStock s left join OriginalCaptureDate h on s.StockId = h.StockId
where
s.HistoryStockId = #HistoryStockId
I've update the code to use CTE but I'm not better off performance wise, only have small performance increase. Any ideas?
Just another note, I need to get to the first record in the history table for StockId and not the earliest Capture date.
I am not certain I understand entirely how the data works from your query but nesting queries like that is never good for performance in my opinion. You could try something along the lines of:
WITH MinCaptureDate (StockID, MinCaptureDate)
AS (
SELECT HS.StockID
,MIN(HS.CaptureDate) AS OriginalCaptureDate
FROM HistoryStock HS
GROUP BY
HS.Description
)
SELECT HS.Description
,MCD.OriginalCaptureDate
FROM HistoryStock HS
JOIN MinCaptureDate MCD
ON HS.StockID = MCD.StockID
WHERE HS.StockID = #StockID
I think i see what you are trying to achieve. You basically want the description of the specified history stock record, but you want the date associated with the first history record for the stock... so if your history table looks like this
StockId HistoryStockId CaptureDate Description
1 1 Apr 1 Desc 1
1 2 Apr 2 Desc 2
1 3 Apr 3 Desc 3
and you specify #HistoryStockId = 2, you want the following result
Description OriginalCaptureDate
Desc 2 Apr 1
I think the following query would give you a slightly better performance.
WITH OriginalStock (StockId, CaptureDate, RowNumber)
AS (
SELECT
StockId,
CaptureDate,
RowNumber = ROW_NUMBER() OVER (PARTITION BY StockId ORDER BY HistoryStockId ASC)
from HistoryStock
)
select
s.Description,
h.CaptureDate
from
HistoryStock s left join OriginalStock h on s.StockId = h.StockId and h.RowNumber = 1
where
s.HistoryStockId = #HistoryStockId