sql number login and create sql query - sql

i have below data
Column
1
0
1
0
1
0
1
1
0
1
1
0
0
0
i need o/p below
1
1
1
0
0
1
1
0
0
1
0

In SQL Server, you can do something like this...
SELECT IIF(id = 0, 1, 0) AS col1
FROM (SELECT id,
Row_number() OVER( ORDER BY (SELECT NULL)) AS rn
FROM tablename) tmp
ORDER BY rn DESC
Result
+------+
| col1 |
+------+
| 1 |
| 1 |
| 1 |
| 0 |
| 0 |
| 1 |
| 0 |
| 0 |
| 1 |
| 0 |
| 1 |
| 0 |
| 1 |
| 0 |
+------+

Related

Compute a Decreasing Cumulative Sum in SQL Server

What I'm trying to achieve is a cumulative sum on a non-negative column where it decreases by 1 on every row, however the result must also be non-negative.
For example, for the following table, summing over the "VALUE" column ordered by the "ID" column:
| ID | VALUE |
-----------------
| 1 | 0 |
| 2 | 0 |
| 3 | 2 |
| 4 | 0 |
| 5 | 0 |
| 6 | 3 |
| 7 | 0 |
| 8 | 2 |
| 9 | 0 |
| 10 | 0 |
| 11 | 0 |
| 12 | 0 |
I expect:
| ID | VALUE | SUM |
-------------------------
| 1 | 0 | 0 |
| 2 | 0 | 0 |
| 3 | 2 | 2 |
| 4 | 0 | 1 |
| 5 | 0 | 0 |
| 6 | 3 | 3 |
| 7 | 0 | 2 |
| 8 | 2 | 3 |
| 9 | 0 | 2 |
| 10 | 0 | 1 |
| 11 | 0 | 0 |
| 12 | 0 | 0 |
Your question is not very well described. My best interpretation is that you want to count down from positive value, starting over when you hit the next one.
You can define the groups with a cumulative sum of the non-zero values. Then use a cumulative sum on the groups:
select t.*,
(case when max(value) over (partition by grp) < row_number() over (partition by grp order by id) - 1
then 0
else (max(value) over (partition by grp) -
(row_number() over (partition by grp order by id) - 1)
)
end) as my_value
from (select t.*,
sum(case when value <> 0 then 1 else 0 end) over (order by id) as grp
from t
) t
Here is a db<>fiddle.
EDIT:
It strikes me that you might want to keep all the "positive" values and count down -- remembering if they don't go down to zero. Alas, I think the simplest method is a recursive CTE in this case:
with tn as (
select t.id, t.value, row_number() over (order by id) as seqnum
from t
),
cte as (
select tn.id, tn.value, tn.seqnum, tn.value as s
from tn
where id = 1
union all
select tn.id, tn.value, tn.seqnum,
(case when cte.s = 0
then tn.value
when tn.value = 0 and cte.s > 0
then cte.s - 1
-- when tn.value > 0 and cte.value > 0
else tn.value + cte.s - 1
end)
from cte join
tn
on tn.seqnum = cte.seqnum + 1
)
select *
from cte;
The db<>fiddle has both solutions.

How to apply a NTILE function to a SQL column

So im trying to establish quantiles over the number of attentions received by some customers, but leaving NULLs and 0 out of the sample and placing them in the 0 and null quantil before applying NTILES function, I'm using this function:
CREATE FUNCTION dbo.RPS_Ntiles (#data int,#percentil int)
RETURNS TABLE
AS
RETURN
SELECT
NTILE(#percentil) OVER(ORDER BY #data DESC) as QUINTIL
WHERE #data > 0
UNION
SELECT
CASE
WHEN CONVERT(int,#data) = 0 THEN 0
WHEN #data is NULL THEN NULL
END AS QUINTIL
WHERE #data = 0 or #data = NULL
Then I'm applying it using CROSS APPLY
SELECT t.QUINTIL,D.[atenciones]
FROM table as D
CROSS APPLY [dbo].[RPS_NTiles](CONVERT(int,D.[atenciones]),5) as t
ORDER BY D.[atenciones] DESC
The result of this query is effective at leaving 0 and nulls out of the NTILEs function but the rest of the data is placed entirely in just 1 quintil like this:
+------------+---------+--+
| Atenciones | Quintil | |
+------------+---------+--+
| 0 | 0 | |
| 0 | 0 | |
| NULL | NULL | |
| 1 | 1 | |
| 3 | 1 | |
| 4 | 1 | |
| 7 | 1 | |
| 46 | 1 | |
| 59 | 1 | |
+------------+---------+--+
And I'm looking for something like this:
+------------+---------+--+
| Atenciones | Quintil | |
+------------+---------+--+
| 0 | 0 | |
| 0 | 0 | |
| NULL | NULL | |
| 1 | 1 | |
| 3 | 2 | |
| 4 | 2 | |
| 7 | 3 | |
| 46 | 4 | |
| 59 | 5 | |
+------------+---------+--+
Why define your own function? You can express this using case logic:
select (case when Atenciones is null or Atenciones = 0
then Atenciones
else ntile(5) over (partition by (case when Atenciones is null or Atenciones = 0 then 1 else 2 end)
order by Atenciones
)
end)

Oracle SQL count and group by multiple fields

I am able to get the data merging two tables to get the following table.
+------------+------+--------+--------+------------+------------+
| Group Name | Type | Manger | Status | ControlOne | ControlTwo |
+------------+------+--------+--------+------------+------------+
| Group A | 1 | 1 | finish | 2 | 2 |
| Group A | 2 | 1 | open | 0 | 2 |
| Group A | 1 | 1 | finish | 0 | 0 |
| Group A | 1 | 2 | finish | 2 | 0 |
| Group B | 1 | 1 | open | 2 | 0 |
| Group B | 1 | 2 | open | 2 | 2 |
| Group B | 2 | 2 | open | 0 | 2 |
| Group B | 2 | 1 | finish | 0 | 0 |
| Group B | 1 | 1 | open | 2 | 0 |
+------------+------+--------+--------+------------+------------+
Now I need to get the total counts based on GroupName/ Type and Manager to have the output for each group in the following format:
+------------+------+-------------------------------------------------+--------------------------------------------+------------------------------+----------------------------+
| Group Name | Type | Manager1Finish | Manager1Open | Manager2Finish | Manager2Open |
+------------+------+-------------------------------------------------+--------------------------------------------+------------------------------+----------------------------+
| Group A | 1 | 2(count of finish by Group A, manager1, type 1) | 0(count of open Manager1, Type 1, Group A) | 1(count of finish Manager 2) | 0(count of open manager 2) |
| Group A | 2 | 0 | 1 | 0 | 0 |
+------------+------+-------------------------------------------------+--------------------------------------------+------------------------------+----------------------------+
Could you please help to how to achieve this?
Try with CASE WHEN:
SELECT GroupName,
TYPE,
COUNT (CASE
WHEN Manager = 1
AND status = 'Finish'
THEN
1
END)
AS Manager1Finish,
COUNT (CASE
WHEN Manager = 1
AND status = 'Open'
THEN
1
END)
AS Manager1Open,
COUNT (CASE
WHEN Manager = 2
AND status = 'Finish'
THEN
1
END)
AS Manager2Finish,
COUNT (CASE
WHEN Manager = 2
AND status = 'Open'
THEN
2
END)
AS Manager2Open
FROM tablename
GROUP BY GroupName, TYPE
select [group], [type],
sum(case when manager=1 and status='finish' then 1 else 0 end) as m1finish,
sum(case when manager=1 and status='open' then 1 else 0 end) as m1open,
sum(...etc...)
from mytable
group by [group],[type]

SQL pivot to arrange data to 12 months output

I have a Table named: ListOfdates
TYPE | O_DATE | C_DATE |
+------+-------------+---------------+
A 15-JAN-2017 (NULL)
A 15-JAN-2017 (NULL)
A 15-JAN-2017 25-APR-2017
A 15-JAN-2017 (NULL)
A 24-FEB-2017 (NULL)
A 15-MAY-2017 (NULL)
B 15-MAY-2017 25-MAY-2017
C 15-MAY-2017 (NULL)
D 15-MAY-2017 26-MAY-2017
A 15-MAY-2017 (NULL)`
I want to arrange it into the below,
`MONTH | Type A |Total| Type B |Total| Type C |Total| Type D |Total|
| A_o | A_c | T_o | B_o | B_c | T_o | C_o | C_c | T_o | D_o | D_c | T_o |
JAN | 4 | 0 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
FEB | 1 | 0 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
MAR | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
APR | 0 | 1 | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
MAY | 2 | 0 | 6 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
JUN | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
...`
The conditions are,
o_date will add a count to open for the month and type.
If c_date is not null, it will add a count to the close for the month and type
else if it is null for the c_date, there won't be a count to the close.
also, there will be a total count for the number of open for each type accumulated from the start of the year.
All 12 months must be displayed.
The acronym are:
`O_DATE = open date
C_DATE = close date
A_o = Type A open
A_c = Type A close
B_o = Type A open
B_c = Type B close
C_o = Type C open
T_o = Total open for the type (example may have 2 type A that is open)
etc...`
Is there a way to do it in sql with pivot?
I would do this using conditional aggregation, but first you have to unpivot the data:
select to_char(dte, 'MON'),
sum(case when type = 'A' then open else 0 end) as A_o,
sum(case when type = 'A' then close else 0 end) as A_c,
sum(case when type = 'A' then 1 else 0 end) as A_total,
. . .
from ((select type, o_date as dte, 1 as open, 0 as close from t) union al
(select type, c_date as dte, 0 as open, 1 as close from t)
) oc
group by to_char(dte, 'MON')
order by min(dte);

Summing Counts into Multiple New Columns Grouped By Another Column

I am trying to subtract two columns and then count how many have the same difference and put those sums into columns. The sums are of how many have a difference of -3 or more, -2, -1, 0, 1, 2, 3 or more grouped by date.
Query must be executed against a DB2 database.
Data...
------------------------------
| Date | Num 1 | Num 2 |
------------------------------
| 2014-02-11 | 19872 | 19873 |
| 2014-02-11 | 19873 | 19873 |
| 2014-02-12 | 19875 | 19873 |
| 2014-02-13 | 19870 | 19873 |
| 2014-02-13 | 19872 | 19873 |
| 2014-02-14 | 19877 | 19869 |
| 2014-02-14 | 19873 | 19873 |
Desired Output...
-----------------------------------------------------------------------
| Date | <= -3 | -2 | -1 | 0 | +1 | +2 | >= +3 |
-----------------------------------------------------------------------
| 2014-02-11 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
| 2014-02-12 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 2014-02-13 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| 2014-02-14 | 1 | 0 | 0 | 1 | 9 | 0 | 0 |
Try this:
select Date,
sum(case when diff <= -3 then 1 else 0 ) AS [<=-3],
sum(case when diff = -2 then 1 else 0 ) AS [-2],
sum(case when diff = -1 then 1 else 0 ) AS [-1],
sum(case when diff = 0 then 1 else 0 ) AS [0],
sum(case when diff = 1 then 1 else 0 ) AS [+1],
sum(case when diff = 2 then 1 else 0 ) AS [+2],
sum(case when diff >= 3 then 1 else 0 ) AS [>=+3]
from
(select Date, Num1, Num2, (Num1-Num2) diff from TableA)TableB
group by Date