filter a view with date - sql-server

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

Related

One column Cross Join with date range

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.

Using the results of WITH clause IN where STATEMENT of main query

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

employee attendance structure using 3 table left innerjoins

SELECT b.Device_Person_ID, a.Personal_id, Date1,
CASE WHEN b.Device_Person_id IS NOT NULL THEN 'A' ELSE 'P' END as Emp_Status
FROM Emp_setting a
LEFT OUTER JOIN (SELECT device_person_id, MAX(logDateTime) AS Date1 FROM tempDeviceLogs
GROUP BY device_person_id) b
ON a.personal_id = b.device_person_id
here i joined only two tables but i need to join 3 tables to show employee details with attendance with specific date.
Required output is
employeename device_person_id designation emptype status
'dbo.persons_profile table
[pesonal_id]
,[Emp_Code]
,[Title]
,[First_name]
,[Middle_name]
,[last_name]
,[Father_Husband_Name]
,[Dob]
,[Age]
,[gender]
,[Marital_status]
,[Nationality]
,[bloodGroup]
,[perAddress]
,[PerStreet]
,[PerLocation]
,[PerCity]
,[PerPincode]
,[CorAddress]
,[CorStreet]
,[CorLocation]
,[CorCity]
,[CorPincode]
,[LandlinePhone]
,[cellNo]
,[EmailId]
,[NosofDependendants]
,[Dependendants_details]
,[Emergency_FirstName]
,[Emergency_Middle_name]
,[Emergency_Last_name]
,[Emergency_WithRelation]
,[Emergency_PhoneNo]
,[Emergency_CellNo]
,[Emergency_emailId]
,[Office_PF_ac_no]
,[ESI_ac_no]
,[JoinedDate]
,[Photofile]
,[ReportTo]
,[Brief_Notes]
,[dateofTermination]
,[termination_note]
,[Print_Priority]
,[DeviceEmployeeID]
,[LogsPermitted]
,[Machin_install_id]
,[Designation]
,[Dept]
,[Section]
,[Groups]
,[EmpWorkingTypeT]'
dbo.tempDeviceLogs table
[LogsID]
,[Device_Person_id]
,[Device_id]
,[logDateTime]
,[logVerifyMode]
,[workCodeID]
,[Machin_install_id]
,[data_loaded_dt]
,[Inout]
dbo.Emp_setting table
[Empset_id]
,[personal_id]
,[DesignationID]
,[DivisionID]
,[Emp_status]
,[Emp_TypeId]
,[Dept_Id]
,[Group_Id]
,[NDIVGRP_CODE]
you need to write to join conditions for achieving what you required.
as an example:
SELECT a.<respective>_id, d.<respective>_title, s.<respective>_id
FROM Emp_setting a
INNER JOIN persons_profile s ON a.<respective>_id = s.<respective>_id
INNER JOIN Emp_setting d ON a.<respective>_id = d.<respective>_id
INNER JOIN tempDeviceLogs b ON s.<respective>_id = b.<respective>_id

TSQL - Return recent date

Having issues getting a dataset to return with one date per client in the query.
Requirements:
Must have the recent date of transaction per client list for user
Will need have the capability to run through EXEC
Current Query:
SELECT
c.client_uno
, c.client_code
, c.client_name
, c.open_date
into #AttyClnt
from hbm_client c
join hbm_persnl p on c.resp_empl_uno = p.empl_uno
where p.login = #login
and c.status_code = 'C'
select
ba.payr_client_uno as client_uno
, max(ba.tran_date) as tran_date
from blt_bill_amt ba
left outer join #AttyClnt ac on ba.payr_client_uno = ac.client_uno
where ba.tran_type IN ('RA', 'CR')
group by ba.payr_client_uno
Currently, this query will produce at least 1 row per client with a date, the problem is that there are some clients that will have between 2 and 10 dates associated with them bloating the return table to about 30,000 row instead of an idealistic 246 rows or less.
When i try doing max(tran_uno) to get the most recent transaction number, i get the same result, some have 1 value and others have multiple values.
The bigger picture has 4 other queries being performed doing other parts, i have only included the parts that pertain to the question.
Edit (2011-10-14 # 1:45PM):
select
ba.payr_client_uno as client_uno
, max(ba.row_uno) as row_uno
into #Bills
from blt_bill_amt ba
inner join hbm_matter m on ba.matter_uno = m.matter_uno
inner join hbm_client c on m.client_uno = c.client_uno
inner join hbm_persnl p on c.resp_empl_uno = p.empl_uno
where p.login = #login
and c.status_code = 'C'
and ba.tran_type in ('CR', 'RA')
group by ba.payr_client_uno
order by ba.payr_client_uno
--Obtain list of Transaction Date and Amount for the Transaction
select
b.client_uno
, ba.tran_date
, ba.tc_total_amt
from blt_bill_amt ba
inner join #Bills b on ba.row_uno = b.row_uno
Not quite sure what was going on but seems the Temp Tables were not acting right at all. Ideally i would have 246 rows of data, but with the previous query syntax it would produce from 400-5000 rows of data, obviously duplications on data.
I think you can use ranking to achieve what you want:
WITH ranked AS (
SELECT
client_uno = ba.payr_client_uno,
ba.tran_date,
be.tc_total_amt,
rnk = ROW_NUMBER() OVER (
PARTITION BY ba.payr_client_uno
ORDER BY ba.tran_uno DESC
)
FROM blt_bill_amt ba
INNER JOIN hbm_matter m ON ba.matter_uno = m.matter_uno
INNER JOIN hbm_client c ON m.client_uno = c.client_uno
INNER JOIN hbm_persnl p ON c.resp_empl_uno = p.empl_uno
WHERE p.login = #login
AND c.status_code = 'C'
AND ba.tran_type IN ('CR', 'RA')
)
SELECT
client_uno,
tran_date,
tc_total_amt
FROM ranked
WHERE rnk = 1
ORDER BY client_uno
Useful reading:
Ranking Functions (Transact-SQL)
ROW_NUMBER (Transact-SQL)
WITH common_table_expression (Transact-SQL)
Using Common Table Expressions

SQL Server T-SQL: Get a records set based on a priority value, startdate and enddate

I am working on an time attendance system. I have to following tables:
Schedule: Contains a Name nvarchar field and a Start and End DateTime fields.
Policy: Contains Start and End DateTime fields too.
PolicySchedule (Cross Table): Contains a Priority int field beside the foreign keys.
End datetime fields are nullable which indicates open periods.
The schedule of the greatest priority will be applied and activated within its time and the policy time.
I need to get a list of the applied schedules within each policy and their activation periods start and end time knowing that shedules may be intersected. Policies are not related here ..
Example:
Schedule_____________Start_________________________End
Schedule1____________01/01/2011 00:00______________04/01/2011 00:00
Schedule2____________04/01/2011 00:00______________11/01/2011 14:00
Schedule3____________11/01/2011 14:00______________02/15/2012 00:00
Schedule2____________02/15/2012 00:00______________01/01/2013 00:00
What is the most efficient way to get the requested result ?
If you have lots of policies and schedules (separately) but few schedules per policy, the most straightforward way would be quite efficient:
WITH dates (policyId, changeDate) AS
(
SELECT policyId, changeDate,
ROW_NUMBER() OVER (PARTITION BY policyId ORDER BY changeDate) AS rn
FROM (
SELECT policyId, startDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
UNION
SELECT policyId, endDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
) q
),
ranges (startDate, endDate)AS
(
SELECT d1.policyId,
d1.changeDate,
d2.changeDate
FROM dates d1
JOIN dates d2
ON d2.policyId = d1.policyId
AND d2.rn = d1.rn + 1
)
SELECT *
FROM policy p
JOIN ranges r
ON r.policyId = p.id
CROSS APPLY
(
SELECT TOP 1 s.*
FROM policySchedules ps
JOIN schedule s
ON ps.policyId = p.id
AND s.id = ps.scheduleId
WHERE ps.startDate BETWEEN r.startDate AND r.endDate
AND ps.endDate BETWEEN r.startDate AND r.endDate
ORDER BY
ps.Priority DESC
)
Assuming you're using SQL Server 2005 or later, you can use an outer apply to look up the policy with the highest priority:
select *
from Schedule s
outer apply
(
select top 1 *
from PolicySchedule ps
join Policy p
on p.id = ps.policyid
where s.StartTime <= p.EndTime
and p.StartTime <= s.EndTime
order by
ps.priority desc
) pol
If there are time periods that have to overlap, you can add a where clause in the outer apply.

Resources