Related
i have m_peserta table.
no_test | name
-----------------------
11 | Mr. X
21 | Mr. Y
31 | Mr. Z
41 | Mr. P
I have result table
no_test | quest_cat | answer
-------------------------------------------
11 | Type I-2 | 1
11 | Type I-5 | 1
11 | Type I-6 | 1
11 | Type II-2 | My Answer is bla
11 | Type II-4 | My Answer is bla
21 | Type I-5 | 1
21 | Type I-6 | 1
21 | Type II-3 | My Answer is bla
21 | Type II-1 | *note : this is a Null Answer
21 | Type III-1| *note : this is a Null Answer
21 | Type III-3| My Answer is bla
and i have a empty table named combine_table with the column is no_test, name, count_quest_I, count_quest_II, count_quest_III.
And i need query "INSERT" from combine table m_peserta and result, so i have a combine_table like this
no_test | name | count_quest_I | count_quest_II | count_quest_III
-----------------------------------------------------
11 | Mr. X | 3 | 2 | 0
21 | Mr. Y | 2 | 1 | 1
please help, thank you
You can try like following.
;WITH cte
AS (SELECT no_test,
Sum(CASE
WHEN quest_cat LIKE 'Type I-%' THEN 1
ELSE 0
END) AS count_quest_I,
Sum(CASE
WHEN quest_cat LIKE 'Type II-%' THEN 1
ELSE 0
END) AS count_quest_II,
Sum(CASE
WHEN quest_cat LIKE 'Type III-%' THEN 1
ELSE 0
END) AS count_quest_III
FROM result
GROUP BY no_test)
INSERT INTO combine_table
SELECT t1.no_test,
t1.NAME,
count_quest_i,
count_quest_ii,
count_quest_iii
FROM m_peserta t1
INNER JOIN cte r
ON r.no_test = t1.no_test
A join with group by will help.
see query below
insert into combine_table
(a.no_test,
a.name,
count_quest_I,
count_quest_II,
count_quest_III)
select
a.no_test,
a.name,
count_quest_I = sum(case when quest_cat like 'Type I-%' then 1 else 0 end),
count_quest_II = sum(case when quest_cat like 'Type II-%' then 1 else 0 end),
count_quest_III = sum(case when quest_cat like 'Type III-%' then 1 else 0 end)
from
m_peserta a join result r
on a.no_test=r.no_test
group by
a.no_test,a.name
I'd used sql server 2012. I want to count maximum consecutive change for each obs. The table like this
snapshot_date customer_id Number Max_consercutive_increase_as_of_each_row
Jan-14 12342 0 0
Feb-14 12342 15 1
Mar-14 12342 45 2
Apr-14 12342 0 2
May-14 12342 15 2
Jun-14 12342 45 2
Jul-14 12342 75 3
Aug-14 12342 105 4
Sep-14 12342 135 5
Oct-14 12342 0 4
Nov-14 12342 0 3
Dec-14 12342 0 2
Jan-15 12342 0 1
Feb-15 12342 0 0
Mar-15 12342 0 0
Apr-15 12342 0 0
As of each rows, count backward to 06 preceding rows (include current row). Of course, some starting rows only 01 or 02 rows before. Increasing based on 'number' column. In 06 rows, if max consecutive between 2 and 3 --> i want take 3.
I try to use cursor with fetch relative -n rows, but my code is not working.
So please help me to resolve it.
Thanks so much!
This should work for you:
-- Create test data
declare #t table(snapshot_date date,customer_id int,Number int);
insert into #t values ('20140101',12342, 0 ),('20140201',12342, 15 ),('20140301',12342, 45 ),('20140401',12342, 0 ),('20140501',12342, 15 ),('20140601',12342, 45 ),('20140701',12342, 75 ),('20140801',12342, 105 ),('20140901',12342, 135 ),('20141001',12342, 0 ),('20141101',12342, 0 ),('20141201',12342, 0 ),('20150101',12342, 0 ),('20150201',12342, 0 ),('20150301',12342, 0 ),('20150401',12342, 0 );
with d as -- Add a row number to the dataset
(
select snapshot_date
,customer_id
,Number
,row_number() over (order by snapshot_date) as rn
from #t
)
,c as -- Use a recursive CTE to loop through the dataset and check for increases
(
select snapshot_date
,customer_id
,Number
,rn
,0 as ConsecutiveIncreases
from d
where rn = 1
union all
select t.snapshot_date
,t.customer_id
,t.Number
,t.rn
,case when t.Number > c.Number then c.ConsecutiveIncreases + 1 else 0 end
from d as t
join c
on t.rn = c.rn+1
)
-- Take the MAX consecutive increase where the current row is also an increase,
-- unless the row is not an increase, then subtract the number of non-increases
-- from the MAX consecutive increase to find the number of increases within the last 6 rows.
-- If less than 6 rows to use, just take the MAX increase.
select c.snapshot_date
,c.customer_id
,c.Number
,case when isnull(sum(c2.ConsecutiveIncreases),0) = 0
then 0
when count(c2.ConsecutiveIncreases) < 6
then max(c2.ConsecutiveIncreases)
else max(c2.ConsecutiveIncreases) - case when c.ConsecutiveIncreases = 0
then sum(case when c2.ConsecutiveIncreases = 0
then 1
else 0
end
)
else 0
end
end as MaxConsecutiveIncreases
from c
left join c as c2
on c2.rn between c.rn-5 and c.rn
group by c.snapshot_date
,c.customer_id
,c.Number
,c.ConsecutiveIncreases
order by 1
Output:
+---------------+-------------+--------+-------------------------+
| snapshot_date | customer_id | Number | MaxConsecutiveIncreases |
+---------------+-------------+--------+-------------------------+
| 2014-01-01 | 12342 | 0 | 0 |
| 2014-02-01 | 12342 | 15 | 1 |
| 2014-03-01 | 12342 | 45 | 2 |
| 2014-04-01 | 12342 | 0 | 2 |
| 2014-05-01 | 12342 | 15 | 2 |
| 2014-06-01 | 12342 | 45 | 2 |
| 2014-07-01 | 12342 | 75 | 3 |
| 2014-08-01 | 12342 | 105 | 4 |
| 2014-09-01 | 12342 | 135 | 5 |
| 2014-10-01 | 12342 | 0 | 4 |
| 2014-11-01 | 12342 | 0 | 3 |
| 2014-12-01 | 12342 | 0 | 2 |
| 2015-01-01 | 12342 | 0 | 1 |
| 2015-02-01 | 12342 | 0 | 0 |
| 2015-03-01 | 12342 | 0 | 0 |
| 2015-04-01 | 12342 | 0 | 0 |
+---------------+-------------+--------+-------------------------+
I have to generate a result set of a SQL query which should match the following, but let me explain both inputs and outputs:
I have a table named Orders and this table has some orders in some days at some hours, then, I have been requested to provide a result-set which should get all days between two dates (i.e. 2017-10-01 and 2017-10-07), with all 24 hours for each day, even if that day or that hour had no orders, but it should be appeared with 0 value.
+------------+------+-------------+
| Day | Hour | TotalOrders |
+------------+------+-------------+
| 2017-10-01 | 0 | 0 |
+------------+------+-------------+
| 2017-10-01 | 1 | 3 |
+------------+------+-------------+
| 2017-10-01 | 2 | 4 |
+------------+------+-------------+
| 2017-10-01 | 3 | 0 |
+------------+------+-------------+
| 2017-10-01 | 4 | 7 |
+------------+------+-------------+
| 2017-10-01 | 5 | 0 |
+------------+------+-------------+
| 2017-10-01 | 6 | 0 |
+------------+------+-------------+
| 2017-10-01 | 7 | 9 |
+------------+------+-------------+
| 2017-10-01 | 8 | 0 |
+------------+------+-------------+
| 2017-10-01 | 9 | 0 |
+------------+------+-------------+
| 2017-10-01 | 10 | 0 |
+------------+------+-------------+
| 2017-10-01 | 11 | 0 |
+------------+------+-------------+
| 2017-10-01 | 12 | 0 |
+------------+------+-------------+
| 2017-10-01 | 13 | 0 |
+------------+------+-------------+
| 2017-10-01 | 14 | 0 |
+------------+------+-------------+
| 2017-10-01 | 15 | 0 |
+------------+------+-------------+
| 2017-10-01 | 16 | 0 |
+------------+------+-------------+
| 2017-10-01 | 17 | 0 |
+------------+------+-------------+
| 2017-10-01 | 18 | 0 |
+------------+------+-------------+
| 2017-10-01 | 19 | 0 |
+------------+------+-------------+
| 2017-10-01 | 20 | 0 |
+------------+------+-------------+
| 2017-10-01 | 21 | 0 |
+------------+------+-------------+
| 2017-10-01 | 22 | 0 |
+------------+------+-------------+
| 2017-10-01 | 23 | 0 |
+------------+------+-------------+
| 2017-10-02 | 0 | 0 |
+------------+------+-------------+
| 2017-10-02 | 1 | 0 |
+------------+------+-------------+
| 2017-10-02 | 2 | 0 |
+------------+------+-------------+
| 2017-10-02 | 3 | 0 |
+------------+------+-------------+
| 2017-10-02 | 4 | 0 |
+------------+------+-------------+
| 2017-10-02 | 5 | 0 |
+------------+------+-------------+
| 2017-10-02 | 6 | 0 |
+------------+------+-------------+
| 2017-10-02 | 7 | 0 |
+------------+------+-------------+
| and so on .................. |
+------------+------+-------------+
So, the above result set should contain every day between the given two dates, and each day should have all 24 hours, irrespective off that day had orders and the same for hour (either it had orders or not)
I did it using a nested CTE:
DECLARE #MinDate DATE = '20171001',
#MaxDate DATE = '20171006';
;WITH INNER_CTE as(
SELECT TOP (DATEDIFF(DAY, #MinDate, #MaxDate) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, #MinDate)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b) ,
OUTER_CTE as (
select * from INNER_CTE
cross apply (
SELECT TOP (24) n = ROW_NUMBER() OVER (ORDER BY [object_id]) -1
FROM sys.all_objects ORDER BY n)) t4
)
select t1.Date, t1.n [Hour], ISNULL(t2.TotalORders,0) TotalOrders from
OUTER_CTE t1
LEFT JOIN orders t2 on t1.Date = t2.[Day] and t1.n = t2.[Hour]
Good Reading about generating sequences using a query here: https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1
I prefer to do this with a tally table instead of using loops. The performance is much better. I keep a tally on my system as a view like this.
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
GO
Now that we have our tally table we can use some basic math to get the desired output. Something along these lines.
declare #Date1 datetime = '2017-10-01';
declare #Date2 datetime = '2017-10-07';
select Day = convert(date, DATEADD(hour, t.N, #Date1))
, Hour = t.N - 1
, TotalOrders = COUNT(o.OrderID)
from cteTally t
left join Orders o on o.OrderDate = DATEADD(hour, t.N, #Date1)
where t.N <= DATEDIFF(hour, #Date1, #Date2)
group by DATEDIFF(hour, #Date1, #Date2)
, t.N
The simplest way is to just use a temporary table or table variable to fill the desired result set, and then count the number of Orders for each row.
declare #Date1 date = '2017-10-01';
declare #Date2 date = '2017-10-07';
declare #Hour int;
declare #Period table (Day Date, Hour Time);
while #Date1 <= #Date2
begin
set #Hour = 0;
while #Hour < 24
begin
insert into #Period (Day, Hour) values (#Date1, TimeFromParts(#Hour,0,0,0,0));
set #Hour = #Hour + 1;
end
set #Date1 = DateAdd(Day, 1, #Date1);
end
select Day, Hour,
(select count(*)
from Orders
where Orders.Day = Period.Day and Orders.Hour = Period.Hour) as TotalOrders
from #Period as Period;
I am currently having difficulty getting the correct values from my table. Here is my table
NOTE: The column Status has 3 possible values (Cleaned, Unclean, Closed)
+-----------+-------------+--------+------------+
|ApplicantID|ApplicantName| Status | HireDate |
+-----------+-------------+--------+------------+
| 1 | John Smith |Cleaned |08/26/2015 |
| 2 | Alex Murphy |Closed |09/12/2015 |
| 3 | Oliver David|Cleaned |01/11/2015 |
| 4 | Max Payne |Unclean |03/18/2015 |
+-----------+-------------+--------+------------+
The output I'm expecting and it should also be sorted by year.
For example I call all these records for the year 2015 which I get using the variable #Year.
NOTE: The column Total is the SUM of Cleaned and Unclean
+---------+-----------+-----------+----------+---------+
| Month | Cleaned | Unclean | Closed | Total |
+---------+-----------+-----------+----------+---------+
| January| 1 | 0 | 0 | 1 |
| February| 0 | 0 | 0 | 0 |
| March | 0 | 1 | 0 | 1 |
| April | 0 | 0 | 0 | 0 |
| May | 0 | 0 | 0 | 0 |
| June | 0 | 0 | 0 | 0 |
| July | 0 | 0 | 0 | 0 |
| August | 1 | 0 | 0 | 1 |
|September| 0 | 0 | 1 | 0 |
| October| 0 | 0 | 0 | 0 |
| November| 0 | 0 | 0 | 0 |
| December| 0 | 0 | 0 | 0 |
+---------+-----------+-----------+----------+---------+
I can't seem to get the right code, for the sql this is my current code.
SELECT Month(HireDate) AS Month, COUNT(*)
FROM Hires
GROUP BY Month(HireDate)
I know my coding is wrong, because it is incomplete.
Generate a list of numbers from 1 to 12 first to hold all months. Then do a LEFT JOIN on Hires to make sure all missing months are accounted for. Then use conditional aggregation for the totals:
SQL Fiddle
;WITH CteMonths AS(
SELECT * FROM(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
)t(N)
)
SELECT
Month = DATENAME(MONTH, DATEADD(MONTH, N-1,0)),
Cleaned = SUM(CASE WHEN h.Status = 'Cleaned' THEN 1 ELSE 0 END),
Closed = SUM(CASE WHEN h.Status = 'Closed' THEN 1 ELSE 0 END),
Unclean = SUM(CASE WHEN h.Status = 'Unclean' THEN 1 ELSE 0 END),
Total = SUM(CASE WHEN h.Status IN('Cleaned', 'Unclean') THEN 1 ELSE 0 END)
FROM CteMonths m
LEFT JOIN Hires h
ON m.N = MONTH(h.HireDate)
--AND YEAR(h.HireDate) = #year --uncomment this line to filter for year.
GROUP BY m.N
ORDER BY m.N
If you want to include the YEAR:
SQL Fiddle
;WITH CteMonths AS(
SELECT * FROM(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
)t(N)
),
CteYears(yr) AS(
SELECT DISTINCT YEAR(HireDate) FROM Hires
),
CteAllDates(dt) AS(
SELECT
DATEADD(MONTH, m.N - 1, DATEADD(YEAR, y.yr - 1900, 0))
FROM CteMonths m
CROSS JOIN CteYears y
)
SELECT
Year = YEAR(d.dt),
Month = DATENAME(MONTH, d.dt),
Cleaned = SUM(CASE WHEN h.Status = 'Cleaned' THEN 1 ELSE 0 END),
Closed = SUM(CASE WHEN h.Status = 'Closed' THEN 1 ELSE 0 END),
Unclean = SUM(CASE WHEN h.Status = 'Unclean' THEN 1 ELSE 0 END),
Total = SUM(CASE WHEN h.Status IN('Cleaned', 'Unclean') THEN 1 ELSE 0 END)
FROM CteAllDates d
LEFT JOIN Hires h
ON MONTH(d.dt) = MONTH(h.HireDate)
AND YEAR(d.dt) = YEAR(h.HireDate)
GROUP BY YEAR(d.dt), MONTH(d.dt), DATENAME(MONTH, d.dt)
ORDER BY YEAR(d.dt), MONTH(d.dt)
If you want to filter for year, say #year = 2015, you can replace the previous ctes with:
;WITH CteMonths AS(
SELECT * FROM(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
)t(N)
),
CteAllDates(dt) AS(
SELECT
DATEADD(MONTH, m.N - 1, DATEADD(YEAR, #year - 1900, 0))
FROM CteMonths m
)...
I suggest to create TEMP table with values from 1 to 12 (numbers of months) and JOIN your table with TEMP table. To achieve values as columns names you can use PIVOT or CASE. You can do It in following:
INSERT INTO #Months VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
SELECT DATENAME(MONTH, DATEADD(MONTH, m.Id-1, 0)) AS [Month]
, SUM(CASE WHEN [Status] = 'Cleaned' THEN 1 ELSE 0 END) AS [Cleaned]
, SUM(CASE WHEN [Status] = 'Closed' THEN 1 ELSE 0 END ) AS [Closed]
, SUM(CASE WHEN [Status] = 'Unclean' THEN 1 ELSE 0 END) AS [Unclean]
, SUM(CASE WHEN [Status] IN ('Unclean', 'Cleaned') THEN 1 ELSE 0 END) AS [Total]
FROM #Test t
RIGHT JOIN #Months m ON m.Id = MONTH(t.HireDate)
GROUP BY m.Id
OUTPUT
+---------+-----------+-----------+----------+---------+
| Month | Cleaned | Unclean | Closed | Total |
+---------+-----------+-----------+----------+---------+
| January | 1 | 0 | 0 | 1 |
| February| 0 | 0 | 0 | 0 |
| March | 0 | 1 | 0 | 1 |
| April | 0 | 0 | 0 | 0 |
| May | 0 | 0 | 0 | 0 |
| June | 0 | 0 | 0 | 0 |
| July | 0 | 0 | 0 | 0 |
| August | 1 | 0 | 0 | 1 |
|September| 0 | 0 | 1 | 0 |
| October | 0 | 0 | 0 | 0 |
| November| 0 | 0 | 0 | 0 |
| December| 0 | 0 | 0 | 0 |
+---------+-----------+-----------+----------+---------+
DEMO
You can test It at: SQL FIDDLE
I have a table output like....
srno billno particular Qty rate vat amount paid balance
1 25 aaa 5 20 5 105 400 135
2 25 qqq 5 50 5 225 400 135
3 25 fff 10 20 5 205 400 135
4 26 aaa 10 20 5 205 300 245
5 26 fff 10 20 5 205 300 245
but I want output like:
srno billno particular Qty rate vat amount paid balance
1 25 aaa 5 20 5 105 400 135
qqq 5 50 5 225
fff 10 20 5 205
2 26 aaa 10 20 5 205 300 245
fff 10 20 5 205
How to get this output with a T-SQL select command....
You should be able to do this by using the ranking functions row_number() and dense_rank:
select
case when rn = 1 then cast(rnk as varchar(10)) else '' end srno,
case when rn = 1 then cast(billno as varchar(10)) else '' end billno,
[particular],
[Qty],
[rate],
[vat],
[amount],
case when rn = 1 then cast([paid] as varchar(10)) else '' end [paid],
case when rn = 1 then cast([balance] as varchar(10)) else '' end [balance]
from
(
select [srno], [billno], [particular], [Qty], [rate], [vat], [amount], [paid], [balance],
row_number() over(partition by billno order by srno) rn,
dense_rank() over(order by billno) rnk
from yourtable
) src;
See SQL Fiddle with Demo
The result is:
| SRNO | BILLNO | PARTICULAR | QTY | RATE | VAT | AMOUNT | PAID | BALANCE |
---------------------------------------------------------------------------
| 1 | 25 | aaa | 5 | 20 | 5 | 105 | 400 | 135 |
| | | qqq | 5 | 50 | 5 | 225 | | |
| | | fff | 10 | 20 | 5 | 205 | | |
| 2 | 26 | aaa | 10 | 20 | 5 | 205 | 300 | 245 |
| | | fff | 10 | 20 | 5 | 205 | | |