I have the following table:
table1
----------------------------
| id | desc | dc | amount |
----------------------------
|1 | trx 1 | d | 100000 |
|2 | trx 2 | d | 500000 |
|3 | trx 3 | c | 800000 |
|4 | trx 4 | d | 100000 |
|5 | trx 5 | c | 900000 |
|6 | trx 6 | d | 700000 |
----------------------------
I need to query from table1 above to have the following output :
----------------------------------
| id | desc | d | c |
----------------------------------
|1 | trx 1 | 100000 | |
|2 | trx 2 | 500000 | |
|3 | trx 3 | | 800000 |
|4 | trx 4 | 100000 | |
|5 | trx 5 | | 900000 |
|6 | trx 6 | 700000 | |
----------------------------------
total | 1500000 | 1700000|
----------------------------------
Please advise what is the SQL command do be executed.
Try this:
SELECT
id, desc,
CASE WHEN dc = 'c' THEN amount ELSE NULL END AS c,
CASE WHEN dc = 'd' THEN amount ELSE NULL END AS d
FROM table1
I suggest you to do something like:
SELECT id, desc,
CASE WHEN dc='d' then amount else null end as d,
CASE WHEN dc='c' then amount else null end as c
FROM table1
Related
I have a table that looks like this
|ID1| ID2| Date |count |
+---+----+------------+------+
|1 | 1 | 2019-07-24 | 3 |
|1 | 1 | 2019-07-25 | 3 |
|1 | 1 | 2019-07-26 | 3 |
|1 | 1 | 2019-07-27 | 1 |
|1 | 1 | 2019-07-28 | -3 |
|1 | 2 | 2019-07-24 | 1 |
|1 | 2 | 2019-07-25 | -3 |
|1 | 2 | 2019-07-26 | 3 |
|1 | 2 | 2019-07-27 | 3 |
|1 | 2 | 2019-07-28 | 3 |
I am interested in calculating the running sum with a min cap of 0 and a max cap of 8. Resulting table would look like this.
|ID1| ID2| Date |count |runningSum|
+---+----+------------+------+----------+
|1 | 1 | 2019-07-24 | 3 | 3 |
|1 | 1 | 2019-07-25 | 3 | 6 |
|1 | 1 | 2019-07-26 | 3 | 8 |
|1 | 1 | 2019-07-27 | 1 | 8 |
|1 | 1 | 2019-07-28 | -3 | 5 |
|1 | 2 | 2019-07-24 | 1 | 1 |
|1 | 2 | 2019-07-25 | -3 | 0 |
|1 | 2 | 2019-07-26 | 3 | 3 |
|1 | 2 | 2019-07-27 | 3 | 6 |
|1 | 2 | 2019-07-28 | 3 | 8 |
I know that Oracle has many different solution to address this problem, like
described here in number 7
https://blog.jooq.org/2016/04/25/10-sql-tricks-that-you-didnt-think-were-possible/. Does anything as simple as this exist for Microsoft SQL Server.
Note that I am not allowed to create tables, temporary tables or table variables.
EDIT I am using Azure Datawarehouse where recursive CTE and cursor statements are not available. Are there really not any other ways to solve this problem in SQL Server?
I don't think you can do this with window functions, alas. The problem is that the caps introduce a state change, so you have to process the rows incrementally to get the value for a given row.
A recursive CTE does iteration, so it can do what you want:
with t as (
select t.*,
row_number() over (partition by id1, id2 order by date) as seqnum
from <yourtable> t
),
cte as (
select id1, id2, date, count,
(case when count < 0 then 0
when count > 8 then 8
else count
end) as runningsum,
seqnum
from t
where seqnum = 1
union all
select cte.id1, cte.id2, t.date, t.count,
(case when t.count + cte.runningsum < 0 then 0
when t.count + cte.runningsum > 8 then 8
else t.count + cte.runningsum
end) as runningsum, t.seqnum
from cte join
t
on t.seqnum = cte.seqnum + 1 and
t.id1 = cte.id1 and t.id2 = cte.id2
)
select *
from cte
order by id1, id2, date;
Here is a db<>fiddle.
Note that very similar code will work in Oracle 12C, which supports recursive CTEs. In earlier versions of Oracle, you can use connect by.
For a set of invoice stage records by project I'm trying to determine a billing cycle using the ID of the starting invoice stage.
Here's the table - InvoiceStages
|ID| Project | StageDate | InvoiceStage | StageFlag | BillCycle |
|1 | abc123 | 10-May-18 | Finance | S | 1 |
|2 | abc123 | 15-May-18 | Review Draft | | 1 |
|4 | abc123 | 19-May-18 | Approved - NO Changes | | 1 |
|7 | abc123 | 21-May-18 | Final Invoice | E | 1 |
|9 | abc123 | 05-Jun-18 | Finance | S | 9 |
|12| abc123 | 07-Jun-18 | Review Draft | | 9 |
|15| abc123 | 09-Jun-18 | Approved - With Changes | | 9 |
|21| abc123 | 10-Jun-18 | Review Draft | | 9 |
|25| abc123 | 12-Jun-18 | Approved - NO Changes | | 9 |
|40| abc123 | 13-Jun-18 | Final Invoice | E | 9 |
|3 | xyz789 | 15-May-18 | Finance | S | 3 |
|5 | xyz789 | 19-May-18 | Review Draft | | 3 |
|6 | xyz789 | 20-May-18 | Approved - NO Changes | | 3 |
|8 | xyz789 | 22-May-18 | Final Invoice | E | 3 |
|10| xyz789 | 06-Jun-18 | Finance | S | 10 |
|11| xyz789 | 07-Jun-18 | Review Draft | | 10 |
|18| xyz789 | 09-Jun-18 | Approved - NO Changes | | 10 |
|22| xyz789 | 11-Jun-18 | Final Invoice | E | 10 |
I've looked at LAG / LEAD but wasn't sure if that would be the best option.
Select
ID
, Project
, StageDate
, InvoiceStage
, StageFlag
, ?? As BillCycle
From InvoiceStages
I expect the output for BillCycle to be the ID of the first record where StageFlag = 'S' for all records up to and including the end stage 'E'. Then the next set will start with the ID starting with 'S' again.
You can assign a group using a cumulative sum and then use a window function to get the value:
select i.*,
max(id) over (partition by project, grp) as invoice_id
from (select i.*,
sum(case when i.stageflag = 'S' then 1 else 0 end) over (partition by i.project order by i.stagedate) as grp
from InvoiceStages i
) i;
If the ids increase along with the date, you can do this without a subquery:
select i.*,
max(case when stageflag = 'S' then id end) over (partition by project) as invoice_id
from invoicestages i;
I have data like this:
|ID|partner_name|quantity|Price|Period |
|1 |partner 1 | 1 | 100 |01/2017|
|2 |partner 1 | 2 | 200 |01/2017|
|3 |partner 1 | 4 | 400 |01/2017|
|4 |partner 1 | 1 | 100 |02/2017|
I want the data to be like this:
|ID|partner_name|quantity|Price|Period |
|1 |partner 1 | 7 | 700 |01/2017|
|2 |partner 1 | 1 | 100 |02/2017|
How can i create that with sql?
thanks,
You should group your query:
SELECT partner_name, SUM(quantity), SUM(price), period FROM your_table
GROUP BY partner_name, period;
This will merge rows with same partner_name and period together.
Here I'm having table 'TABLE_1' as
|ID | Name | ACID1 | ACVALUE1 | ACID2 | ACVALUE2 | ACID3 | ACVALUE3 |
|----------------------------------------------------------------------
| 1 |ABC | 10 | 82.50 | 20 | 175.95 | 40 | 125.75 |
| 2 |IJK | 30 | 120.55 | 20 | 68.30 | 50 | 25.45 |
| 3 |LMN | 40 | 62.50 | 10 | 87.25 | 30 | 40.50 |
----------------------------------------------------------------------
Another table is AC_TABLE whose ID is recored in above table as ACID1,ACID2,...
___________________
|ID | Name |
|-------------------
|10 | AC1 |
|20 | AC2 |
|30 | AC3 |
|40 | AC4 |
|50 | AC5 |
-------------------
Now what all i want the result in following format
_____________________________
ID | Name | ACName | ACVALUE
------------------------------
1 | ABC | AC1 | 82.50
1 | ABC | AC2 | 175.95
1 | ABC | AC4 | 125.75
2 | IJK | AC3 | 120.55
2 | IJK | AC2 | 68.30
2 | IJK | AC5 | 25.45
3 | LMN | AC4 | 62.50
3 | LMN | AC1 | 87.25
3 | LMN | AC3 | 40.50
-------------------------------
Please help me to get the desired result.
Use Cross Apply to unpivot multiple columns.
First unpivot the Table_1 using cross apply then join the result with the ac_table table. Try this.
SELECT a.id,
a.name,
b.name AS ACName,
cs.ACValue
FROM Table_1 a
CROSS apply (VALUES (ACVALUE1,ACID1),
(ACVALUE2,ACID2),
(ACVALUE3,ACID3))cs(acvalue, ac)
JOIN ac_table b
ON cs.ac = b.id
SQLFIDDLE DEMO
I have a table named class
|Record_No [PK] | Student_No | Class_No | Seat_No |
=====================================================
|1 | 200910 | 2 | 20 |
|2 | 201234 | 2 | 13 |
|3 | 200965 | 2 | 1 |
|4 | 200920 | 2 | 8 |
|5 | 200911 | 2 | 9 |
|6 | 200955 | 1 | 10 |
|7 | 200924 | 1 | 9 |
|8 | 200922 | 1 | 1 |
|9 | 200901 | 2 | 11 |
|10 | 200902 | 2 | 18 |
is it possible to update the numbers in Seat_No in order from 1 up to the last count of Seat No where its class no is equal to 2?
the table should look like this:
|Record_No [PK] | Student_No | Class_No | Seat_No |
=====================================================
|1 | 200910 | 2 | 1 |
|2 | 201234 | 2 | 2 |
|3 | 200965 | 2 | 3 |
|4 | 200920 | 2 | 4 |
|5 | 200911 | 2 | 5 |
|6 | 200955 | 1 | 10 |
|7 | 200924 | 1 | 9 |
|8 | 200922 | 1 | 1 |
|9 | 200901 | 2 | 6 |
|10 | 200902 | 2 | 7 |
as of now, i can only achieve this by using
UPDATE class SET Seat_No = 1 WHERE Class_No = 2 AND Student_No = 200910;
UPDATE class SET Seat_No = 2 WHERE Class_No = 2 AND Student_No = 201234;
...
and so on..
How can i solve this without putting every student_no in the query? pls help.
update class
set seat_no = s.rn
from (
select
row_number() over(order by record_no) rn,
record_no
from class
where class_no = 2
) s
where class.record_no = s.record_no
If you want to update all classes:
update class
set seat_no = s.rn
from (
select
row_number() over(partition by class_no order by record_no) rn,
record_no
from class
) s
where class.record_no = s.record_no
Assuming your Record_No is 1-5 in your example, you can use it:
UPDATE class SET Seat_No = Record_No WHERE Class_No = 2
If not, it depends on your RDBMS.
Here is the postgresql approach:
UPDATE Class C
SET Seat_No = t.rn
FROM (
SELECT Record_No, ROW_NUMBER() OVER (ORDER BY Record_No) rn
FROM Class
WHERE Class_no = 2
) t
WHERE C.Record_No = t.Record_No
SQL Fiddle Demo