Sql Query issue and error regarding groupby cause - sql

I am trying to calculate the total number of Projects in every year. and also how many projects are active, how many of them are canceled.
I tried to group by cause for PRojects dates so we have a total number of project in every year but I am not sure where to start and what to do
Select ts.Id as projectid ,
--a.ParentObjectId,
ts.RequestName as ProjectDates,
ts.Type,
ts.Category,
ts.SubType,
ts.status as projectstatus,
Count (ts.ReceptionDate),
cast (ts.ReceptionDate as Date) as ReceptionDate,
from [rpt].[TransmissionServicesRpt] ts
left join [dbo].[AuditHistory] a on a.ParentObjectId = ts.Id
Left join [dbo].[User] u on a.CreatedById = u.id
Group by ts.id, ts.ReceptionDate
+ -------------+--------+-----------+------------+----------+-----------------+
| New Projects | Active | Cancelled | Terminated | Inactive | Carried Forward |
+ -------------+--------+-----------+------------+----------+-----------------+
| 2013 | 32 | 45 | 4 | 11 | 30 |
| 2014 | 45 | 75 | 17 | 14 | 44 |
| 2015 | 46 | 90 | 25 | 21 | 44 |
| 2016 | 30 | 74 | 27 | 10 | 37 |
| 2017 | 82 | 119 | 11 | 26 | 82 |
| 2018 | 86 | 168 | 29 | 24 | 115 |
| 2019 | 23 | 138 | 9 | 4 | 125 |
+ -------------+--------+-----------+------------+----------+-----------------+

You want one result row per year. So group by year. You get it via YEAR or DATEPART. Then count conditionally:
select
year(receptiondate) as year,
count(*) as total,
count(case when status = 'Active' then 1 end) as active,
count(case when status = 'Cancelled' then 1 end) as cancelled,
count(case when status = 'Terminated' then 1 end) as terminated,
count(case when status = 'Inactive' then 1 end) as inactive,
count(case when status = 'Carried Forward' then 1 end) as carried_forward
from rpt.transmissionservicesrpt
group by year(receptiondate)
order by year(receptiondate);

Related

SQL Grouping by year gives incorrect results

I am trying to summerize sales date, by month, sales region and type. The problem is, the results change when I try to group by year.
My simplified query is as follows:
SELECT
DAB700.DATUM,DAB000.X_REGION,DAB700.BELEG_ART, // the date, sales region, order type
// calculate the number of orders per month
COUNT (DISTINCT CASE WHEN MONTH(DAB700.DATUM) = 1 THEN DAB700.BELEG_NR END) as jan,
COUNT (DISTINCT CASE WHEN MONTH(DAB700.DATUM) = 2 THEN DAB700.BELEG_NR END) as feb,
COUNT (DISTINCT CASE WHEN MONTH(DAB700.DATUM) = 3 THEN DAB700.BELEG_NR END) as mar
FROM "DAB700.ADT" DAB700
left join "DAB050.ADT" DAB050 on DAB700.BELEG_NR = DAB050.ANUMMER // join to table 050, to pull in order info
left join "DF030000.DBF" DAB000 on DAB050.KDNR = DAB000.KDNR // join table 000 to table 050, to pull in customer info
left join "DAB055.ADT" DAB055 on DAB050.ANUMMER = left (DAB055.APNUMMER,6)// join table 055 to table 050, to pull in product info
WHERE (DAB700.BELEG_ART = 10 OR DAB700.BELEG_ART = 20) AND (DAB700.DATUM>={d '2021-01-01'}) AND (DAB700.DATUM<={d '2021-01-11'}) AND DAB055.ARTNR <> '999999' AND DAB055.ARTNR <> '999996' AND DAB055.TERMIN <> 'KW.22.22' AND DAB055.TERMIN <> 'KW.99.99' AND DAB050.AUF_ART = 0
group by DAB700.DATUM,DAB000.X_REGION,DAB700.BELEG_ART
This returns the following data, which is correct (manually checked):
| DATUM | X_REGION | BELEG_ART | jan | feb | mar |
|------------|----------|-----------|-----|-----|-----|
| 04.01.2021 | 1 | 10 | 3 | 0 | 0 |
| 04.01.2021 | 3 | 10 | 2 | 0 | 0 |
| 04.01.2021 | 4 | 10 | 1 | 0 | 0 |
| 04.01.2021 | 4 | 20 | 1 | 0 | 0 |
| 04.01.2021 | 6 | 20 | 2 | 0 | 0 |
| 05.01.2021 | 1 | 10 | 1 | 0 | 0 |
and so on....
The total number of records for Jan is 117 (correct).
Now I now want to summerize the data in one row (for example, data grouped by region and type)..
so I change my code so that I have:
SELECT
YEAR(DAB700.DATUM),
and
group by YEAR(DAB700.DATUM)
the rest of the code stays the same.
Now my results are:
| EXPR | X_REGION | BELEG_ART | jan | feb | mar |
|------|----------|-----------|-----|-----|-----|
| 2021 | 1 | 10 | 16 | 0 | 0 |
| 2021 | 1 | 20 | 16 | 0 | 0 |
| 2021 | 2 | 10 | 19 | 0 | 0 |
| 2021 | 2 | 20 | 22 | 0 | 0 |
| 2021 | 3 | 10 | 12 | 0 | 0 |
| 2021 | 3 | 20 | 6 | 0 | 0 |
Visually it is correct. But, the total count for January is now 116. A difference of 1. What am I doing wrong?
How can I keep the results from the first code - but have it presented as per the 2nd set?
You count distinct BELEG_NR. This is what makes the difference. Let's look at an example. Let's say your table contains four rows:
DATUM
X_REGION
BELEG_ART
BELEG_NR
04.01.2021
1
10
100
04.01.2021
1
10
200
05.01.2021
1
10
100
05.01.2021
1
10
300
That gives you per day, region and belegart:
DATUM
X_REGION
BELEG_ART
DISTINCT COUNT BELEG_NR
04.01.2021
1
10
2
05.01.2021
1
10
2
and per year, region and belegart
YEAR
X_REGION
BELEG_ART
DISTINCT COUNT BELEG_NR
2021
1
10
3
The BELEG_NR 100 never appears more than once per day, so every instance gets counted. But it appears twice for the year, so it gets counted once instead of twice.

SQL last 15 months of sales grouped by customer

I would like to output in sql a table that contains the monthly sales per customer. Each column should correspond to another month.
First column should be current month example my sql columns are:
customer
invoicedate
sales
Original table looks like this:
+------------+------------+---------+
| Customer | invdate | sales |
+------------+------------+---------+
| Best Buy | 03-12-2019 | 433 |
| Walmart | 03-15-2019 | 543 |
| Home Depot | 12-12-2018 | 32 |
+------------+------------+---------+
Desired Output:
+------------+----------+--------+--------+--------+--------+----------+
| Customer | March 19 | Feb 19 | Jan 19 | Dec 18 | Nov 18 | Oct 18 |
+------------+----------+--------+--------+--------+--------+----------+
| Home Depot | 100 | 300 | 244 | 32 | 322 | 43 |
| Walmart | 543 | 222 | 234 | 12 | 234 | 34 |
| Bestbuy | 433 | 323 | 323 | 23 | 433 | 34 |
+------------+----------+--------+--------+--------+--------+----------+
You can use group by, sum, and case to good effect, like this:
select
customer,
sum(case when year(invdate) = year(getdate) and month(invdate) = month(getdate()) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,1,getdate))
and month(invdate) = month(dateadd(m,1,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,2,getdate))
and month(invdate) = month(dateadd(m,2,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,3,getdate))
and month(invdate) = month(dateadd(m,3,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,4,getdate))
and month(invdate) = month(dateadd(m,4,getdate())) then sales else o end),
sum(case when year(invdate) = year(dateadd(m,5,getdate))
and month(invdate) = month(dateadd(m,5,getdate())) then sales else o end)
from tableyoudidnotgivethenameof
group by customer

Query to get the count of data for particular customer with all other data from table

My table structure is as follows:
group_id | cust_id | ticket_num
------------------------------
60 | 12 | 1
60 | 12 | 2
60 | 12 | 3
60 | 12 | 4
60 | 30 | 5
60 | 30 | 6
60 | 31 | 7
60 | 31 | 8
65 | 02 | 1
I want to fetch all the data for group_id=60 and find the count of ticket_num for each customer in that group. My output should be like this:
cust_id | ticket_count | ticket_num
------------------------------
12 | 4 | 1
12 | | 2
12 | | 3
12 | | 4
30 | 2 | 5
30 | | 6
31 | 2 | 7
31 | | 8
I tried this query:
SELECT gd.cust_id, Count(gd.cust_id),gd.ticket_num
FROM Group_details gd
WHERE gd.group_id = 65
GROUP BY gd.cust_id;
But this query is not working.
You appear to want the ANSI/ISO standard row_number() functions and count() as a window function:
select gd.cust_id, count(*) over (partition by gd.cust_id) as num_tickets,
row_number() over (order by gd.cust_id) as ticket_seqnum
from group_details gd
where gd.group_id = 60;
use aggregate and subquery
select t2.*,t1.ticket_num from Group_details t1
inner join
(
SELECT gd.cust_id, Count(gd.ticket_num) as ticket_count
FROM Group_details gd where gd.group_id = 60
GROUP BY gd.cust_id
) t2 on t1.cust_id=t2.cust_id
http://sqlfiddle.com/#!9/dd718b/1

SQL Server 2008 Combine or test rows based on value

I have a table that looks something like this:
+------------+---------+--------+---------+--------+--------+
| emplname | JAN | FEB | MAR | APR | MAY |
+------------+---------+--------+---------+--------+--------+
| ALLEN | NULL | NULL | 17 | 17 | 17 |
| ALLEN | 17 | 17 | 205 | NULL | NULL |
| ADAMS | NULL | NULL | 14 | 14 | 17 |
| BROWN | NULL | 205 | 13 | 13 | 13 |
| BROWN | 12 | 12 | NULL | NULL | NULL |
+------------+---------+--------+---------+--------+--------+
I want to combine the rows where the emplname is the same and ignoring 205 values, so for ALLEN, I would get
| ALLEN | 17 | 17 | 17 | 17 | 17 |
for BROWN it would be
| BROWN | 12 | 12 | 13 | 13 | 13 |
Basically what I want to do is be able to find if, per employee, if a column has two entries for it except if it is an entry plus 205, i can ignore 205. What I want to find is something like this:
| BROWN | NULL | 13 | 13 | 13 | 13 |
| BROWN | 12 | 12 | NULL | NULL | NULL |
where that third column has 13 and 12 for that one employee. I am looking for things like that. if it exists, return the emplname. Hope that makes sense.
You could try this (I think I am understanding you correctly, this will output names of employees who need two rows)
SELECT emplname FROM yourtable
GROUP BY emplname
HAVING COUNT(CASE WHEN JAN = 205 THEN NULL ELSE JAN END) > 1 OR
COUNT(CASE WHEN FEB = 205 THEN NULL ELSE FEB END) > 1 OR
COUNT(CASE WHEN MAR = 205 THEN NULL ELSE MAR END) > 1 OR
COUNT(CASE WHEN APR = 205 THEN NULL ELSE APR END) > 1 OR
COUNT(CASE WHEN MAY = 205 THEN NULL ELSE MAY END) > 1
Let me know if that was what you have in mind; I think it answers the second part of the question.
Join the table to itself and then use the following statement
COALESCE(CASE WHEN table1.fieldname = 205 THEN NULL ELSE table1.fieldname END,
CASE WHEN table2.fieldname = 205 THEN NULL ELSE table2.fieldname END,0)
I use 0 here to mark an error but you could leave it out so you get null when you have a problem.
Try this SQL:
SELECT T.emplname
, ISNULL(T.JAN,IIF(T205.JAN=205,NULL,T205.JAN))
, ISNULL(T.FEB,IIF(T205.FEB=205,NULL,T205.FEB))
, ISNULL(T.MAR,IIF(T205.MAR=205,NULL,T205.MAR))
, ISNULL(T.APR,IIF(T205.APR=205,NULL,T205.APR))
, ISNULL(T.MAY,IIF(T205.MAY=205,NULL,T205.MAY))
FROM myTable as T left join myTable as T205 on T.emplname = T205.emplname
AND (T.JAN <> 205 AND T.FEB <> 205 AND T.MAR <> 205
AND T.APR <> 205 AND T.MAY <> 205)
AND (T205.JAN = 205 OR T205.FEB = 205 OR T205.MAR = 205
OR T205.APR = 205 OR T205.MAY = 205)

Return Max(Recent_Date) for each month, Duplicate value and inner join issue - SQL

Basically, I want to achieve , for each months, like in this example, from January until March 2013, what is the Max(Most_Recent_Day) for each users.
Example, From January to March, every month in the Database, systems will capture the Most_Recent_Day for each users.
Below are the expected results:
User | Most_Recent_Day
--------------------------------
afolabi.banu | 1/31/2013
afolabi.banu | 2/7/2013
afolabi.banu | 3/21/2013
mario.sapiter | 1/22/2013
mario.sapiter | 2/7/2013
mario.sapiter | 3/11/2013
However, I want to have another DB column as well to be display .Below is the column.
User|Total_Hits | Recent_Month| Most_Recent_Day | Most_Recent_Days_Hits
I tried to use inner join, but the result are not what i expect. I got duplicated user name and duplicated recent day. Basically, I want only to display no duplicated record for the same user name.
Below is the result that I got. Please ignore the recent_month value since it's data from database.
User |Total_Hits | Recent_Month | Most_Recent_Day | Most_Recent_Days_Hits
-------------------------------------------------------------------------------------
afolabi.banu | 223 | 25 | 2/7/2013 | 5
afolabi.banu | 223 | 25 | 2/7/2013 | 5
afolabi.banu | 211 | 13 | 1/31/2013 | 3
afolabi.banu | 223 | 25 | 2/7/2013 | 5
afolabi.banu | 296 | 31 | 3/21/2013 | 1
afolabi.banu | 296 | 31 | 3/21/2013 | 1
mario.sapiter | 95 | 7 | 2/7/2013 | 5
mario.sapiter | 7 | 7 | 3/21/2013 | 1
mario.sapiter | 7 | 37 | 3/22/2013 | 1
mario.sapiter | 249 | 37 | 2/7/2013 | 5
This is my SQL Code
SELECT t.[User],
t.Total_Hits,
t.Recent_Month,
t.Most_Recent_Day,
t.Most_Recent_Day_Hits FROM UserUsageMonthly t
INNER JOIN
(
select
[User]
, max(Most_Recent_Day) as Most_Recent_Day
from UserUsageMonthly (NoLock)
where Application_Name='Daily Production Review' and Site_Collection='wrm13'
and Most_Recent_Day between '1/1/2013' and '3/31/2013'
group by [User], datepart(month,Most_Recent_Day)
) table2
ON
t.[User]=table2.[User]
AND t.Most_Recent_Day = table2.Most_Recent_Day
order by t.[User]
You should add the month value to your SQL SELECT
SELECT
MONTH(t.Most_Recent_Day) as 'MyMonth',
t.[User],
t.Total_Hits,
t.Recent_Month,
t.Most_Recent_Day,
t.Most_Recent_Day_Hits FROM UserUsageMonthly t
Then you can group by the month column
GROUP BY MyMonth