DATEDIF Report builder can i do an OR or where - sql-server

I am building a report where I need to display the number of days an item was with a customer in the chosen month.
#Month is set as a parameter and the report is filtered based on the month a user chooses.
I have DATEDIFF(d, dbo.Rental.StartDateTime, { fn NOW() }) + 1 AS [Days Live] however this isn't what I need.
A rental could start before the chosen month or part way through. It could end and any date in the chosen month or not have been ended at all. so for example if running the report for November (assuming i am now in December) i could have a rental that started (dbo.Rental.StartDateTime) 15th October and ended (dbo.Rental.EndDateTime) 11th November. I would need the field to say 11 however if there is no end date i would need it to say 30
I have formatted both fields to be dd/mm/yyy. The dataset is also doing various other things in terms of displaying the relevant records.
My entire dataset is below.
SELECT TOP (100) PERCENT System_1.SystemTypeId, System_1.Id, System_1.CancellationCode, System_1.RentalId, Format(System_1.CreatedOnDateTime, 'dd/MM/yyyy') AS [Assembled Date],
Format(dbo.Rental.StartDateTime, 'dd/MM/yyyy') AS [Start Date], DATEPART(month, dbo.Rental.StartDateTime) AS [Start Date Month], dbo.Rental.Revision, dbo.Rental.RentalNumber, dbo.Rental.RentalStatus, dbo.Customer.Name AS Customer, dbo.Site.Name AS Site,
dbo.Location.Name AS Location, dbo.Rental.SpecialInstructions, DATEDIFF(d, dbo.Rental.StartDateTime, { fn NOW() }) + 1 AS [Days Live], dbo.SystemType.Description, Format(dbo.Rental.EndDateTime,
'dd/MM/yyyy') AS [End Date], DATEPART(month, dbo.Rental.EndDateTime) AS [End Date Month]
FROM dbo.SystemType INNER JOIN
dbo.System AS System_1 INNER JOIN
dbo.Contract ON System_1.ContractId = dbo.Contract.Id INNER JOIN
dbo.Customer ON dbo.Contract.CustomerId = dbo.Customer.Id ON dbo.SystemType.Id = System_1.SystemTypeId LEFT OUTER JOIN
dbo.Location INNER JOIN
dbo.Rental ON dbo.Location.Id = dbo.Rental.LocationId INNER JOIN
dbo.Site ON dbo.Location.SiteId = dbo.Site.Id ON System_1.Id = dbo.Rental.SystemId
WHERE (dbo.Rental.RentalStatus NOT LIKE 'PendingActivations') AND dbo.customer.ID = #Customer AND ((DATEPART(month, dbo.Rental.StartDateTime) = #Month) OR (DATEPART(month, dbo.Rental.EndDateTime) = #Month) OR ( (DATEPART(month, dbo.Rental.StartDateTime) < #Month) AND (dbo.Rental.EndDateTime IS NULL )))
ORDER BY System_1.Id

Related

SQL finding the total weight

tables diagram
Code used:
SELECT
ROUND(SUM(COALESCE(p.[Weight], 0)), 2) AS [Total weight]
FROM
SalesLT.SalesOrderHeader soh
JOIN
SalesLT.SalesOrderDetail sod ON sod.SalesOrderID = soh.SalesOrderID
JOIN
SalesLT.Product p ON p.ProductID = sod.ProductID
WHERE
DATEPART(YEAR, soh.DueDate) = '2017'
AND DATEPART(MONTH, soh.DueDate) = '05'
OR (DATEPART(MONTH, soh.DueDate) = '06'
OR DATEPART(MONTH, soh.DueDate) = '12')
AND soh.ShipMethod = 'Unknown';
I got this question wrong and was wondering if someone could see what was wrong with the code? Looks right to me.
Question:
What's the total weight in kilograms of orders due in May 2017, or June 2017, or December 2017? Only include orders which used an Unknown shipping method. Get the total weight, rounded and padded to 2dp.
You need both unit weight multiplied by the quantity of those units. If one ships a single item - or - 100 of those items the total weight is not the same.
Plus, you need to couple the year restriction with each of the month restrictions so you get 2017-04, 2017-07, 2017-11. In you original you get 2017-04 but any rows in months 7 and 11. Use parentheses to control the meaning of the predicates.
SELECT
ROUND(SUM(COALESCE(p.[Weight] * sod.OrderQty, 0)), 2) AS [Total weight]
FROM SalesLT.SalesOrderHeader soh
JOIN SalesLT.SalesOrderDetail sod
ON sod.SalesOrderID = soh.SalesOrderID
JOIN SalesLT.Product p
ON p.ProductID = sod.ProductID
WHERE soh.ShipMethod = 'UnKnown'
AND DATEPART(YEAR, soh.DueDate) = 2017
AND (
DATEPART(MONTH, soh.DueDate) = 04
OR DATEPART(MONTH, soh.DueDate) = 07
OR DATEPART(MONTH, soh.DueDate) = 11
)
as mentioned by marc_s also avoid the type conversion as datepart() returns integers.
Personally I would prefer to use 3 full date ranges instead of using datepart
WHERE soh.ShipMethod = 'UnKnown'
AND (soh.DueDate >= '20170401' and soh.DueDate < '20170501')
AND (soh.DueDate >= '20170701' and soh.DueDate < '20170801')
AND (soh.DueDate >= '20171101' and soh.DueDate < '20171201')

SQL Server : Membership Renewals

I am new to this website but I've referenced this website a lot in the past to guide me along my current class.
Our teacher assigned us some homework and we created a database that has online seminars. The members in the database pay for the online seminars. They can pay in either 4 different ways: Monthly, quarterly, yearly, or every 2 years. I created a renewal table that assigns a RenewalID for each of the subscription levels and is used as a foreign key in the Members table to indicate their level of subscription.
Here's the question that the teacher is asking:
Members are charged for renewals according to their payment plan (monthly, quarterly, etc..) on the anniversary of the date they joined. A user who joined on the 7th should always be billed on the 7th, whether it's every one, three or 12 months. Some method is needed to scan for current members who are up for renewal and to initiate the billing to their credit card.
I was thinking to create a view that would display their card information when it's time to bill to them. I couldn't figure out the monthly, quarterly, or 2 year cycles but I used the following to calculate the yearly renewal:
select pc.*
from Members m
inner join paymentcard pc on pc.memberid = m.MemberID
where
CurrentFlag <> 0
and DATEPART(month, startdate) = DATEPART(MONTH, getdate())
and datepart(day, startdate) = DATEPART(day, getdate())
and RenewalID = 2
However, after messing around more, I'm beginning to realize that it's going to be more than just a view. I believe it needs to be a stored procedure. I'm not exactly sure how I would go about doing this..
I'm turning to the wonderful members of this website to help me figure this out.. thanks!
I ended up figuring it out with another student. This is what we came up with. Also, the teacher said this works so I'm content.
I understand how useful this website is so I will post the solution I found and also the solution my instructor came up with to help anyone in the future.
My solution:
First, I created the view:
GO
CREATE VIEW vwRenewal
AS
select m.memberid, m.FirstName, m.LastName, m.StartDate, m.RenewalID, r.RenewalPrice, pc.CardID
from Members m
inner join
Renewal r
on m.RenewalID = r.RenewalID
inner join
PaymentCard pc
on pc.MemberID = m.MemberID
WHERE m.CurrentFlag <> 0 AND m.RenewalID = 4
AND DATEPART(day, startdate) = DATEPART(day, getdate())
UNION ALL
select m.memberid, m.FirstName, m.LastName, m.StartDate, m.RenewalID, r.RenewalPrice, pc.CardID
from Members m
inner join
Renewal r
on m.RenewalID = r.RenewalID
inner join
PaymentCard pc
on pc.MemberID = m.MemberID
WHERE m.CurrentFlag <> 0 AND m.RenewalID = 3
AND DATEPART(day, startdate) = DATEPART(day, getdate())
AND DATEPART(month, GETDATE()) IN
((select (datepart(month, m.startdate) + 3)),
(select (datepart(month, m.startdate) + 6)),
(select (datepart(month, m.startdate) + 9)))
UNION ALL
select m.memberid, m.FirstName, m.LastName, m.StartDate, m.RenewalID, r.RenewalPrice, pc.CardID
from Members m
inner join
Renewal r
on m.RenewalID = r.RenewalID
inner join
PaymentCard pc
on pc.MemberID = m.MemberID
WHERE m.CurrentFlag <> 0 AND m.RenewalID = 2
AND DATEPART(day, startdate) = DATEPART(day, getdate())
AND DATEPART(month, startdate) = DATEPART(month, getdate())
UNION
ALL
select m.memberid, m.FirstName, m.LastName, m.StartDate, m.RenewalID, r.RenewalPrice, pc.CardID
from Members m
inner join
Renewal r
on m.RenewalID = r.RenewalID
inner join
PaymentCard pc
on pc.MemberID = m.MemberID
WHERE m.CurrentFlag <> 0 AND m.RenewalID = 1
AND GETDATE() IN
((SELECT dateadd(month, 24, m.startdate)),
(select dateadd(month, 48, m.startdate)),
(select dateadd(month, 72, m.startdate)))
GO
Then, the stored procedure:
CREATE PROCEDURE sp_Renewal
AS BEGIN
IF EXISTS (select * from vwRenewal) BEGIN
INSERT INTO Transactions (CardID, TransactionDate, Charge, Result)
VALUES ( (select CardID
from vwRenewal),
getdate(),
(select RenewalPrice
from vwRenewal),
'Pending')
END SELECT * FROM Transactions WHERE Result = 'Pending'
END
Instructor solution:
-- Determine the member's next charge date based on the last time they were charged.
DECLARE #RETURNDATE DATE -- Return value
DECLARE #SUBLEVEL INT -- Member's subscription level
DECLARE #MEMBERDAYS INT -- Days in member subscription period
DECLARE #JOINDATE DATE -- Date member joined
DECLARE #LASTCHARGE DATE -- Last charge to member account
-- Get subscription level and days in subscription period.
SELECT #SUBLEVEL = m.SubscriptionLevel, #MEMBERDAYS = s.DaysPerPeriod, #JOINDATE = m.JoinDate
FROM Members m
INNER JOIN SubscriptionLevels s
ON s.SubLevelID = m.SubscriptionLevel
WHERE MemberID = #MemberID
-- If the member's subscription level is not free...
IF #SUBLEVEL NOT IN (SELECT SubLevelID FROM SubscriptionLevels WHERE RenewalAmt > 0)
BEGIN
-- Get the most recent account charge date for the member.
-- There should always be a charge date, even for new members.
SELECT TOP 1 #LASTCHARGE = ChargeDate
FROM AccountCharges
WHERE MemberID = #MemberID
ORDER BY ChargeDate DESC
-- If there is a charge date, add the number of days in the membership period
-- to get the new date. Otherwise, add it to the join date.
IF #LASTCHARGE IS NOT NULL
SET #RETURNDATE = DATEADD(DAY, #MEMBERDAYS, #LASTCHARGE)
ELSE
SET #RETURNDATE = DATEADD(DAY, #MEMBERDAYS, #JOINDATE) -- Just in case there's no previous charge.
END
ELSE
-- If the member has a free plan, just add one year to today so the member is never charged.
SET #RETURNDATE = DATEADD(YEAR, 1, GETDATE())
RETURN #RETURNDATE
END
GO
Note: I only post this to help people in the future in some way who may encounter a similar situation as me or whatever they need it for..
Hope this helps. Enjoy.
Like any code, this is only a couple ways to accomplish this task. There are many other ways I'm sure..

How to set date clause for prevous month in sql?

I want to get last values for prevous month (universal, not just for january :))
How can I set up where condition? Now it works well for current month, but i want result for prevous.
SELECT MAX(v.timestamp) AS Date,
MAX(v.value) AS Stanje,
v.tag_id, t.prik_sifr, t.tag_name
FROM dbo.tag_values AS v INNER JOIN
dbo.typ_tag AS t ON v.tag_id = t.id
WHERE (t.prik_sifr IS NOT NULL) AND (t.unit = 'M3') AND
(DATEPART(YEAR, v.timestamp) = DATEPART(YEAR, SYSDATETIME())) AND
(DATEPART(MONTH, v.timestamp)= DATEPART(MONTH, SYSDATETIME())) GROUP BY v.tag_id, t.prik_sifr, t.tag_name)
You need to subtruct one month from the current date:
SELECT MAX(v.timestamp) AS Date,
MAX(v.value) AS Stanje,
v.tag_id, t.prik_sifr, t.tag_name
FROM dbo.tag_values AS v INNER JOIN
dbo.typ_tag AS t ON v.tag_id = t.id
WHERE (t.prik_sifr IS NOT NULL) AND (t.unit = 'M3') AND
(DATEPART(YEAR, v.timestamp) = DATEPART(YEAR, DATEADD(MONTH, -1 SYSDATETIME()))) AND
(DATEPART(MONTH, v.timestamp)= DATEPART(MONTH, DATEADD(MONTH, -1 SYSDATETIME())))
GROUP BY v.tag_id, t.prik_sifr, t.tag_name)

How to get a list of months and year between two dates in SQL Server

I have to get the list of months and year in between my dates. Currently it only returns month and year for dates that has data associated with it.
for example my dates is between: '8'+'/1'+'/'+'2015' and DATEADD(mm, 15, '8'+'/1'+'/'+'2016'
It only prints out: May2016, June2016, July2016, Auguest2016, September2016
I want it to print out all of the months and year in between. Here is my sql queries:
select d.id_base as case_id,
c.C_LAST_ACTION AS Docketed,
c.C_CASE_TYPE AS caseType,
ct.C_NAME As caseName,
ct.C_DESCRIPTION AS caseNameDescription,
case when d.c_mod_decision_id is not null then '' else DATENAME(mm, d.c_issue_date) + DATENAME(yyyy, d.c_issue_date) end as display
from t_case_decision d JOIN T_CASE_INPUT c on c.id = d.id_base JOIN T_CASE_TYPE ct on C_CASE_TYPE = ct.id
where cast(d.c_issue_date AS date) BETWEEN '8'+'/1'+'/'+'2015' and DATEADD(mm, 15, '8'+'/1'+'/'+'2016')
First, create a numbers table
CREATE TABLE Numbers(N INT)
insert into Numbers(N)
select top 1000000 row_number() over(order by t1.number) as N
from master..spt_values t1
cross join master..spt_values t2
then use DATEADD to list dates between desired values, like this
declare #iniDate as date
set #iniDate='20150801'
select dateadd(MONTH,N,#iniDate) dates
from Numbers
where N<15 order by N
These returns dates from #iniDate up to 15 months later
EDIT: try this, I don't have sql right now
select datename(mm, dateadd(MONTH,N,#iniDate))+datename(yyyy ,dateadd(MONTH,N,#iniDate)) display
from ( select top 15row_number() over(order by t1.number) as N
from master..spt_values t1
cross join master..spt_values t2) numbers right join (
select d.id_base as case_id,
c.C_LAST_ACTION AS Docketed,
c.C_CASE_TYPE AS caseType,
ct.C_NAME As caseName,
ct.C_DESCRIPTION AS caseNameDescription,
case when d.c_mod_decision_id is not null then '' else DATENAME(mm, d.c_issue_date) + DATENAME(yyyy, d.c_issue_date) end as display
from t_case_decision d JOIN T_CASE_INPUT c on c.id = d.id_base JOIN T_CASE_TYPE ct on C_CASE_TYPE = ct.id
where cast(d.c_issue_date AS date) BETWEEN '8'+'/1'+'/'+'2015' and DATEADD(mm, 15, '8'+'/1'+'/'+'2016')
sql-server
) qq
on datename(mm, dateadd(MONTH,N,#iniDate))+datename(yyyy ,dateadd(MONTH,N,#iniDate)) = qq.display
where N<15 order by N
If I understand what you're trying to accomplish, a recursive CTE might help. Here's a quick example of what you can do. The CTE will expand out into a list of dates, which you can then use as the base for your query.
The contents of the TargetData CTE may need to be adjusted, as I don't have a complete picture of your data structure.
DECLARE #startDate DATE = '1/1/2015';
DECLARE #endDate DATE = '7/31/2016';
-- Recursive CTE to generate a list of months within the date range:
WITH Months AS (
SELECT CONVERT(DATE, DATEADD(D, -(DAY(#startDate)) + 1, #startDate)) [MonthDate]
UNION ALL
SELECT DATEADD(M, 1, MonthDate)
FROM Months
WHERE MonthDate <= DATEADD(M, -1, #endDate)
),
TargetData AS (
-- This is a slightly modified version of the original query:
select
d.id_base as case_id,
c.C_LAST_ACTION AS Docketed,
c.C_CASE_TYPE AS caseType,
ct.C_NAME As caseName,
ct.C_DESCRIPTION AS caseNameDescription,
case when d.c_mod_decision_id is not null then '' else DATENAME(mm, d.c_issue_date) + DATENAME(yyyy, d.c_issue_date) end as display,
-- Return the "MonthDate" so that it can be left joined to the Months table:
DATEADD(D, -(DAY(d.c_issue_date)) + 1, d.c_issue_date) [MonthDate]
from t_case_decision d JOIN T_CASE_INPUT c on c.id = d.id_base JOIN T_CASE_TYPE ct on C_CASE_TYPE = ct.id
where cast(d.c_issue_date AS date) BETWEEN #startDate AND #endDate
)
SELECT
m.MonthDate,
DATENAME(mm, m.MonthDate) + DATENAME(yyyy, m.MonthDate),
td.*
FROM Months m
LEFT JOIN TargetData td ON td.MonthDate = m.MonthDate;
You need to join on primary keys between tables, I haven't seen a between statement with that syntax. So I suggest trying the following:
SELECT d.id_base as case_id, c.C_LAST_ACTION AS 'Docketed',c.C_CASE_TYPE AScaseType,ct.C_NAME As 'caseName', ct.C_DESCRIPTION AS 'caseNameDescription'
,CASE
WHEN d.c_mod_decision_id is not null THEN '' AS 'null_val'
ELSE CONCAT(YEAR(d.c_issue_dateDATENAME), MONTH(d.c_issue_date))
END AS 'display'
FROM t_case_decision d INNER JOIN T_CASE_INPUT c on c.id = d.id_base
INNER JOIN T_CASE_TYPE ct on c.id = ct.id
WHERE CONVERT(DATE,d.c_issue_date) BETWEEN '08/01/2015'
AND '08/01/2016';
I hope this helps or points you in the right direction :)

How to return values from SQL server database within intervals

Hi I have an SQL server database with 3 columns Activity[start_date(datetime),end_date(datetime),title(string)]
and I wish to count for a whole year, how many activities have start_date in each month, I mean I would like a return of 12 values(12 months) that count the activities within the months, thanks.
If there is an index on start_date and/or if you need to include months in the result even if there was no activity in that month, you might consider this one:
DECLARE #year INT;
SET #year = 2012;
;WITH n AS
(
SELECT TOP (12) m = DATEADD(MONTH, ROW_NUMBER() OVER
(ORDER BY name)-1, DATEADD(YEAR, #year-1900, 0))
FROM sys.all_objects ORDER BY name
)
SELECT [Month] = n.m, ActivityCount = COUNT(t.title)
FROM n
LEFT OUTER JOIN dbo.unspecified_table_name AS t
ON t.start_date >= n.m
AND t.start_date < DATEADD(MONTH, 1, n.m)
GROUP BY n.m
ORDER BY [Month];
(If you don't want a row when there were zero activities in a given month, then change LEFT OUTER to INNER.)
select month(start_date) as Month, count(*) as Count
from Activity
where year(start_date) = 2011
group by month(start_date)
order by month(start_date)

Resources