Query for date groupings? - sql-server

I have a Client table with basic demographics in rows and a date of birth row (DOB) with a DATE data type.
I'm trying to make a query that will take my entries and count how many clients are between the ages of 18-60, 61-79, 80+. I'm not sure if I'm having a brain-fart, but I can't figure out how to gather that info from my table...
So what I have is:
Last Name First Name DOB
Stein Ethel 1954-01-20
Frank Sam 1981-05-65
etc...
What I want to have is:
Ages 18-60
6
Ages 61-79
10
Ages 80+
20
Any recommendations to proceed?

Using #Alex's suggestion
declare #today datetime
set #today =getdate()
select
s as [start],
e as [end],
count(1) as [count]
from Client join
(values (0,17),(18,60),(61,79),(80,9999)) as ranges(s,e)
on datediff(yy,dob,#today) between s and e
-- where buildingid=1
group by s,e
See demo here

Related

SQL First and Last Transaction Report

I have a table in SQL, that looks a little similar to the table below:
[enter image description here]
My goal is to generate a first and Last Transaction report.
I want to know when did customer X make their first purchase and what is the date of their most recent purchase.
I would like to group my results by Store and add all the transaction if they happen on the same day.
For instance, if John do made 2 expenses at walmart on Jan 15th and that's their most recent transaction, I would like those two expenses to be Summed in my report.
Here is the final result I'd expect from a table like on the example above:
[enter image description here]
With what I have tried so far,
I am only getting 1 value back
The SQL looks a little similar to
Select
SN
, SID
, CustomerName
, BankAccount
, Min(TransDate)
, Max(TransDate)
, price
, store
From transaction
GROUp by
SN
, SID
, CustomerName
, BankAccount
, Min(TransDate)
, Max(TransDate)
, price
, store
I know I have to use some types of nested query to get the result(maybe) but I have been unsuccessful.
I would try and pull out the customer info you need to filter out the rest of the data. I would start with a CTE to get the MIN and MAX dates for each customer. I would then JOIN that back up to the original table and just get the records for the Customer that are on that MAX date.
I would assume you have something that is more Unique then the customer name, and if so I would use that instead. But here is what I came up with given the data you provided:
CREATE TABLE #tmp(SerialNumber int, SearialID int,CustomerName varchar(100), BankAccount int,
TranDate date, Price decimal(10,2),TracerID int,Store varchar(20))
INSERT INTO #tmp VALUES
(2,2,'Peter Smith',14564,'1/1/2021',10,756,'Kroger'),
(1,1,'John Do',12345,'1/1/2021',10,156,'Walmart'),
(1,1,'John Do',12345,'1/15/2021',5,148,'Walmart'),
(1,1,'John Do',12345,'1/15/2021',15,148,'Walmart'),
(2,2,'Peter Smith',14564,'1/12/2021',12,756,'Kroger')
;WITH CTE AS
(
SELECT Min(TranDate) FirstDate, Max(TranDate) LastDate, CustomerName
FROM #tmp
GROUP BY CustomerName
)
SELECT T.SerialNumber,T.SearialID,T.CustomerName,t.BankAccount,C.FirstDate FirstTrans, C.LastDate,SUM(t.Price) Price,T.Store
FROM #tmp T
INNER JOIN CTE C on t.CustomerName = c.CustomerName and t.TranDate = c.LastDate
GROUP BY T.SerialNumber,T.SearialID,T.CustomerName,t.BankAccount,C.FirstDate,C.LastDate,T.Store

Get customers age in months from a given column (SQL Server 2017)

I am new to SQL just wanted to know if I have one row with date of birth of few customers and I have to create a new column while creating a view with the customer_id and customer age in month as of today(Age_in_months = Current date - Date of birth of customer). How do I do it ?
I have tried date diff , some suggested to use floor and cast but I keep getting errors
One of them
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value '01-05-1974' to data type int.
Can somebody please suggest a very simple solution to this?
Thank you!
Thanks you as I see your query works fine went data is inserted manually . I imported the CSV file so this created a string type entry in sql . Your query gave me the same error I just had to fix it with convert
select customer_Id ,
DOB, DATEDIFF(month, CONVERT(date, Customer.DOB, 103), GETDATE()) as
[Age In Months] from Customer;
Since you haven't provided the Table or Column names I will assume the Table is Customers and the columns are id and dob.
Here is some example SQL to get the information
select
id as [Customer ID],
dob as [Date Of Birth],
datediff(month, cast(dob AS DATE), getdate()) as [Age In Months]
from
customers
First, we will take the Date Of Birth and make sure it is a date and not a Varchar or int, then we wrap that in a DATEDIFF to get the difference between the date in the dob column and the current date in months.
And this is the output
Customer ID Date Of Birth Age In Months
----------- ----------------- -------------
1 01-01-1991 331
2 01-01-2018 7

Crystal Reports sales report showing all dates even when not existing

I have been searching for answers on this for a couple of days but not found any useful results.
A bit of the backstory:
I have about ~20k items that i'm trying to do a lifetime sales history report on.Some items have history from 1/1/2005. Sales are only noted on dates they occur.
Trying to graph first lifetime of sales history by days, first 6mo of sales, and last 30 days of sales. I don't have permission to add a temp table, so i am working with importing an excel file. (and for some reason you can't right-outer-join it to invoice date. im guessing because it's external?)
My problem is that there HAS to be a simple way to tell crystal to include/print missing dates without a lookup table. I've already got the start and end dates passed to parameters.
Isn't there a way to dynamically generate missing dates between {?PM-Start} to {?PM-End}? Using a lookup table to check if all days from 1/1/2005-currentdate match is 90,000,000,000 extra bloops to check.
That would take hours to run. It should be able to grab minumum(sale_date), and maximum(sale_date) and plop a record for each day whether it exists in the DB or not. (How is this not already a basic function?)
Or am I just missing something super simple?
Isn't there any way to dynamically generate missing dates between {?PM-Start} to {?PM-End}? Using a lookup table to check if all days from 1/1/2005-currentdate match is 90,000,000,000 extra bloops to check.
By using a query like below you can generate a calendar view to fill missing date:
;with years(yyyy) as (
select 2005
union all
select yyyy + 1
from years
where yyyy < datepart(year, getdate())
), months(mm) as (
select 1
union all
select mm + 1
from months
where mm < 12
), allDays(dd) as (
select 1
union all
select dd + 1
from allDays
where dd < 31
), calendar as (
select --datefromparts(y.yyyy, m.mm, d.dd) [date]
cast(cast(y.yyyy as varchar(4))+'-'+cast(m.mm as varchar(2))+'-'+cast(d.dd as varchar(2)) as date) [date]
from allDays d
cross join
months m
cross join
years y
where isdate(cast(y.yyyy as varchar(4))+ '/'+cast(m.mm as varchar(2))+'/'+cast(d.dd as varchar(2))) <> 0
)
select *
from calendar;
SQL Fiddle Demo

How to get new clients by months in SQL Server

I have a table Clients.
Every client has da_reg (date registered in our system). I need to make a report:
By months - total number of clients (count(distinct customernumber)); and new customers by da_reg date (I can do this per month like insert all clients from past month into temp table and then compare WHERE da_reg < 'date' and customerid not in (select customerid from #temp) - however it takes a lot of time to every time compare).
How to make it easiest way? In 1-2 steps?
Please help!
Thanks in advance!
please try this
select count(*) as new_count,
month(da_reg) as month,year(da_reg) as year
(select count(*) from tbl a where tbl.da_reg>=a.da_reg) as total_cus
from tbl
group by month(da_reg),year(da_reg)
You can Select DAtE_TIME column by month and then calc an number of row :Example for August
SELECT *,count(a.id)
FROM TABLE A as a
WHERE DATEPART(month, MY_DATETIME) = 8
where a.id PK of A

Query to create records between two dates

I have a table with the following fields (among others)
TagID
TagType
EventDate
EventType
EventType can be populated with "Passed Inspection", "Failed Inspection" or "Repaired" (there are actually many others, but simplifies to this for my issue)
Tags can go many months between a failed inspection and the ultimate repair... in this state they are deemed to be "awaiting repair". Tags are still inspected each month even after they have been identified as having failed. (and just to be clear, a “failed inspection” doesn’t mean the item being inspected doesn’t work at all… it still works, just not at 100% capacity…which is why we still do inspections on it).
I need to create a query that counts, by TagType, Month and Year the number of Tags that are awaiting repair. The end result table would look like this, for example
TagType EventMonth EventYear CountofTagID
xyz 1 2011 3
abc 1 2011 2
xyz 2 2011 2>>>>>>>>>>>>indicating a repair had been made since 1/2011
abc 2 2011 2
and so on
The "awaiting repair" status should be assessed on the last day of the month
This is totally baffling me...
One thought that I had was to develop a query that returned:
TagID,
TagType,
FailedInspectionDate, and
NextRepairDate,
then try and do something that stepped thru the months in between the two dates, but that seems wildly inefficient.
Any help would be much appreciated.
Update
A little more research, and a break from the problem to think about it differently gave me the following approach. I'm sure its not efficient or elegant, but it works. Comments to improve would be appreciated.
declare #counter int
declare #FirstRepair date
declare #CountMonths as int
set #FirstRepair = (<Select statement to find first repair across all records>)
set #CountMonths = (<select statement to find the number of months between the first repair across all records and today>)
--clear out the scratch table
delete from dbo.tblMonthEndDate
set #counter=0
while #counter <=#CountMonths --fill the scratch table with the date of the last day of every month from the #FirstRepair till today
begin
insert into dbo.tblMonthEndDate(monthenddate) select dbo.lastofmonth(dateadd(m,#counter, #FirstRepair))
set #counter = #counter+1
end
--set up a CTE to get a cross join between the scratch table and the view that has the associated first Failed Inspection and Repair
;with Drepairs_CTE (FacilityID, TagNumber, CompType, EventDate)
AS
(
SELECT dbo.vwDelayedRepairWithRepair.FacilityID, dbo.vwDelayedRepairWithRepair.TagNumber, dbo.vwDelayedRepairWithRepair.CompType,
dbo.tblMonthEndDate.MonthEndDate
FROM dbo.vwDelayedRepairWithRepair INNER JOIN
dbo.tblMonthEndDate ON dbo.vwDelayedRepairWithRepair.EventDate <= dbo.tblMonthEndDate.MonthEndDate AND
dbo.vwDelayedRepairWithRepair.RepairDate >= dbo.tblMonthEndDate.MonthEndDate
)
--use the CTE to build the final table I want
Select FacilityID, CompType, Count(TagNumber), MONTH(EventDate), YEAR(EventDate), 'zzz' as EventLabel
FROM Drepairs_CTE
GROUP BY FacilityID, CompType, MONTH(EventDate), YEAR(EventDate)`
Result set ultimately looks like this:
FacilityID CompType Count Month Year Label
1 xyz 2 1 2010 zzz
1 xyz 1 2 2010 zzz
1 xyz 1 7 2009 zzz
Here is a recursive CTE which generates table of last dates of months in interval starting with minimum date in repair table and ending with maximum date.
;with tableOfDates as (
-- First generation returns last day of month of first date in repair database
-- and maximum date
select dateadd (m, datediff (m, 0, min(eventDate)) + 1, 0) - 1 startDate,
max(eventDate) endDate
from vwDelayedRepairWithRepair
union all
-- Last day of next month
select dateadd (m, datediff (m, 0, startDate) + 2, 0) - 1,
endDate
from tableOfDates
where startDate <= endDate
)
select *
from tableOfDates
-- If you change the CTE,
-- Set this to reasonable number of months
-- to prevent recursion problems. 0 means no limit.
option (maxrecursion 0)
EndDate column from tableOfDates is to be ignored, as it serves as upper bound only. If you create UDF which returns all the dates in an interval, omit endDate in select list or remove it from CTE and replace with a parameter.
Sql Fiddle playground is here.

Resources