I have following table which has multiple entries for an order and the order can either be rejected or approved.
Amount | Approved | Rejected | OrderNo
-------------------------------------------
10 | N | Y | 10
20 | Y | N | 10
30 | N | N | 10
40 | Y | N | 10
22 | N | Y | 11
10 | N | N | 10
--------------------------------------------
Want to build a result set which can summarise.
OrderNo | TotalEntries | Approved_Or_Rejected_Entries | TotalAmount
-----------------------------------------------------------------
10 | 5 | 3 | 110
11 | 1 | 1 | 22
Use conditional aggregation:
select
orderno,
count(*) totalentries
sum(case when 'Y' in (approved, rejected) then 1 else 0 end) approved_or_rejected
sum(amount) total_amount
from mytable
group by orderno
Related
I have two tables payroll_est_act, actual_payroll_history
payroll_est_act
id| location_id | type | amt
-------------------------------------------
1 | 1 | Actual | 36000
2 | 1 | Estimated | 20000
3 | 2 | Actual | 50000
4 | 2 | Estimated | 50000
5 | 3 | Actual | 24000
6 | 3 | Estimated | 18000
actual_payroll_history
id | payroll_est_act_id | amt | date
-----------------------------------------------------
1 | 1 | 4000 | 1 June 20
2 | 1 | 4000 | 1 July 20
3 | 1 | 4000 | 1 Aug 20
4 | 1 | 4000 | 1 Sep 20
5 | 2 | 12500 | 1 June 20
6 | 2 | 12500 | 1 July 20
7 | 2 | 12500 | 1 Aug 20
8 | 2 | 12500 | 1 Sep 20
9 | 3 | 4000 | 1 June 20
I want to write an update statement to update the amount in payroll_est_act for 'actual' type with the sum of amounts for the corresponding payroll_est_act_id from actual_payroll_history if the value of amt from payroll_est_act does not match with the sum of amt from actual_payroll_history.
Please help.
Thanks
I would use an updatable CTE here:
WITH cte1 AS (
SELECT payroll_est_act_id, SUM(amt) AS amt_actual
FROM actual_payroll_history
GROUP BY payroll_est_act_id
),
cte2 AS (
SELECT p.amt, t.amt_actual
FROM payroll_est_act p
INNER JOIN cte1 t
ON t.payroll_est_act_id = p.location_id
WHERE p.type = 'Actual'
)
UPDATE cte2
SET amt = amt_actual
WHERE amt <> amt_acutal;
EDIT I forget an important detail
I have a postgresql table like this:
| id | n_1 | n_2 |
| 1 | 3 | 5 |
| 1 | 2 | 6 |
| 1 | 8 | 4 |
| 1 | 1 | 5 |
| 2 | 4 | 3 |
| 2 | 5 | 1 |
I want to get the min values and the count count only if n_2 >= min(n_1):
| id | n_1 | n_2 | count |
| 1 | 1 | 4 | 4 |
| 2 | 4 | 1 | 0 |
The min number from n_1, min number from n_2 and count total when n_2 >= min(n_1) records from each id.
Any help?
here how you can do it by grouping them by id :
select id , min(n_1) ,min(n_2), count(case when n_2 >= min_n_1 then 1 end)
from ( select *, min(n_1) over (partition by id) as min_n_1 from table) t
group by id
I think this is just aggregation:
select id, min(n_1), min(n_2), count(*)
from t
group by id;
I'm sure this is really straightforward, but I'm struggling! I'd like to create a group by for the count of the incidence of a value, eg. there are two incidences of case_id '10' and two of case_id '20', so there would be two counts of 'two'
Data table:
id | case_id
---------------
0 | 10
1 | 10
2 | 20
3 | 20
4 | 30
5 | 30
6 | 30
7 | 40
8 | 40
7 | 40
8 | 40
Creates this:
no of occurrences | count
of a case_id |
---------------------------
2 | 2
3 | 1
4 | 1
Thank you!
Use an inner query:
SELECT occurences, COUNT(*) cnt
FROM (
SELECT COUNT(*) occurences FROM mytable GROUP BY case_id
) x
GROUP BY occurences
Demo on DB Fiddle:
| occurences | cnt |
| ---------- | --- |
| 2 | 2 |
| 3 | 1 |
| 4 | 1 |
I have a tabel that looks like this:
|--------+------+---------|------|
| Head | ID | Amount | Rank |
|--------+------+---------|------|
| 1 | 10 | 1000 | 1 |
| 1 | 11 | 1200 | 2 |
| 1 | 12 | 1500 | 3 |
| 2 | 20 | 3400 | 1 |
| 2 | 21 | 3600 | 2 |
| 2 | 22 | 4200 | 3 |
| 2 | 23 | 1700 | 4 |
|--------+------+---------|------|
I want a new column (New_column) that does the following:
|--------+------+---------|------|------------|
| Head | ID | Amount | Rank | New_column |
|--------+------+---------|------|------------|
| 1 | 10 | 1000 | 1 | 1000 |
| 1 | 11 | 1200 | 2 | 1000 |
| 1 | 12 | 1500 | 3 | 1200 |
| 2 | 20 | 3400 | 1 | 3400 |
| 2 | 21 | 3600 | 2 | 3400 |
| 2 | 22 | 4200 | 3 | 3600 |
| 2 | 23 | 1700 | 4 | 4200 |
|--------+------+---------|------|------------|
Within each Head number, if rank is not 1, takes the amount of row within the Head number with Rank number before it (Rank 2 takes the amount of Rank 1 within the same Head and Rank 3 takes the amount of Rank 2 within the same Head and so on...)
I know how to fix it with a For loop in other programming languages but Don't know how to do it with SQL.
I think you basically want lag():
select t.*,
lag(amount, 1, amount) over (partition by head order by rank) as new_column
from t;
The three-argument form of lag() allows you to provide a default value.
You can join the same table(subquery) on rank-1 of derived table.
select t1.*,case when t1.rank=1 then amount else t2.amount new_amount
from your_table t1 left join (select Head,ID,Amount,Rank from your_table) t2
on t1.head=t2.head and t1.rank=t2.rank-1
You can use this update:
UPDATE your_table b
SET New_column = CASE WHEN rank = 1 then Amount
ELSE (select a.Amount FROM your_table a where a.ID = b.ID and a.rank = b.rank-1) END
I have an issue where I need group a set of values and increase the group number when the variance between 2 columns is greater than or equal to 4, please see below.
UPDATE: I added a date column so you can view the order, but I need the group to update based off of the variance not the date.
+--------+-------+-------+----------+--------------+
| Date | Col 1 | Col 2 | Variance | Group Number |
+--------+-------+-------+----------+--------------+
| 1-Jun | 2 | 1 | 1 | 1 |
| 2-Jun | 1 | 1 | 0 | 1 |
| 3-Jun | 3 | 2 | 1 | 1 |
| 4-Jun | 4 | 1 | 3 | 1 |
| 5-Jun | 5 | 1 | 4 | 2 |
| 6-Jun | 1 | 1 | 0 | 2 |
| 7-Jun | 23 | 12 | 11 | 3 |
| 8-Jun | 12 | 11 | 1 | 3 |
| 9-Jun | 2 | 1 | 1 | 3 |
| 10-Jun | 13 | 4 | 9 | 4 |
| 11-Jun | 2 | 1 | 1 | 4 |
+--------+-------+-------+----------+--------------+
The group number is simply the number of times that 4 or greater appears in the variance column. You can get this using a correlated subquery:
select t.*,
(select 1 + count(*)
from table t2
where t2.date < t.date and t2.variance >= 4
) as GroupNumber
from table t;
In SQL Server 2012+, you can also do this using a cumulative sum:
select t.*,
sum(case when variance >= 4 then 1 else 0 end) over
(order by date rows between unbounded preceding and 1 preceding
) as GroupNumber
from table t;