I have the following pivot query:
select *
from
(
select order_id,unit_price,quantity,sum(unit_price*quantity)
over (partition by order_id) as Total
from DEMO_ORDER_ITEMS
) tbla
pivot
(
sum(unit_price*quantity) as unit_totals
for unit_price in(30,50,60,80,110,120,125,150)
) tblb
order by order_id;
producing following result:
ORDER_ID TOTAL 30_UNIT_TOTALS 50_UNIT_TOTALS 60_UNIT_TOTALS 80_UNIT_TOTALS 110_UNIT_TOTALS 120_UNIT_TOTALS 125_UNIT_TOTALS 150_UNIT_TOTALS
1 1890 500 640 750
2 2380 60 250 180 480 220 240 500 450
3 1640 100 240 320 480 500
4 1090 180 200 220 240 250
5 950 150 180 320 300
6 1515 330 360 375 450
7 905 90 250 120 320 125
8 1060 160 330 120 450
9 730 240 240 250
10 870 250 320 300
I would like to change order of columns ending with the TOTAL. How can i select the columns in preferred order?
This works:select tblb.* .... but select tblb.30_UNIT_TOTALS fails.
You have to quote fields if they don't start with an alphabetic character. In addition, using quotes make the identifier case sensitive. So you have to write:
tblb."30_UNIT_TOTALS"
From the documentation
Nonquoted identifiers must begin with an alphabetic character from your database character set. Quoted identifiers can begin with any character.
[...]
Nonquoted identifiers are not case sensitive. Oracle interprets them as uppercase. Quoted identifiers are case sensitive.
Related
In a table like this
acc_id time approved_amount balance
11 Jan14 580 500
11 Feb14 580 400
11 Mar14 580 300
11 Apr14 580 200
22 Jan14 . 800
22 Feb14 . 700
22 Mar14 . 600
I want to create a column orig_amount that would be equal to approved_amount if this is not null and to the first value of balance - to balance at time = min(time) by acc_id if approved_amount is null.
Therefore the desired output would look like this:
acc_id time approved_amount balance orig_amount
11 Jan14 580 500 580
11 Feb14 580 400 580
11 Mar14 580 300 580
11 Apr14 580 200 580
22 Jan14 . 800 800
22 Feb14 . 700 800
22 Mar14 . 600 800
I have now this
create table second_table as
select *,
coalesce(approved_amount, case when time = min(time) then
balance end ) as orig_amount
from first_table
group by acc_id
order by acc_id, time;
But still not the desired result. Can anybody help please?
You can use the first_value() window function and coalesce().
SELECT acc_id,
time,
approved_amount,
balance,
coalesce(approved_amount,
first_value(balance) OVER (PARTITION BY acc_id
ORDER BY time)) orig_amount
FROM first_table;
db<>fiddle
I have a table as below. I want to do a group by in such a way that 1-4 weeknums are joined together and 5-8 weeknums are joined together. Or in other words i want to get the monthly total from below fields
table1
weeknum amount
1 1000
2 1100
3 1200
4 1300
5 1400
6 1500
7 1600
8 1700
The output i need is as below
output
max(weeknum) sum(amount)
4 4600
8 6200
The below answer did not work exactly for my actual values as below. I want to start with 4 weeks grouping. The formula (weeknum-1)/4 returns 3 groups as in the expected is only 2
weeknum Group Expr Expected Group Expr
1855 463 463
1856 463 463
1857 464 463
1858 464 463
1859 464 464
1860 464 464
1861 465 464
1862 465 464
Need to execute the query in oracle
Try using FLOOR that rounds the number down in the group by clause:
SELECT MAX(t.weeknum),sum(amount)
FROM table1 t
GROUP BY FLOOR((t.weeknum-1)/4)
This will make sure every 4 weeks are treated as a group :
(1-1)/4 -> 0
(2-1)/4 -> 0
...
(5-1)/4 -> 1
Hello currently I have a working script below. I am using Oracle 10
SELECT z.no as "ID_One",
MAX(r.value) as "Max",
round(MAX(r.value)/80000,2) as "ROUND"
FROM Table1 r, Table2 z
WHERE r.timestamp > ((SYSDATE - TO_DATE('01/01/1970 00:00:00', 'MM-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60) - 80000
AND r.va=21
AND r.nor IN ('7','98','3','3')
AND r.nor = z.re
GROUP BY r.nor, r.varr, z.no;
It produces a table like this
ID_ONE MAX ROUND
105 500 232
106 232 32
333 23 .21
444 34 .321
I want to select a row call timestamp from table r. However when I add " r.timestamp " in to my query it produces 500 rows of data instead of 4. It looks like it is producing the the highest number for each timestamp instead. How would I produce a table that looks like this ? fyi timestamp column is in unix time. I can do the conversion myself. I just need to know how to get out these rows.
ID_ONE MAX ROUND TIMESTAMP
105 500 232 DEC 21,2021 10:00
106 232 32 DEC 21,2021 23:12
333 23 .21 DEC 31,2021 2:12
444 34 .321 DEC 31,2021 23:12
When I add the column time stamp it does not create what is above. What I am getting instead is something like that looks like this the other two ids are below in this 500 long row of data. I only wanted the 4 that is the highest value (MAX) from this set of time. ID_ONE is my id for a stock of inventory for a warehouse.
ID_ONE ROUND TIMESTAMP MAX
106 338
.06 1406694567
106 355
.06 1406696037
106 246
.04 1406696337
106 363
.06 1406700687
106 330
.06 1406700987
106 512
.09 1406701347
106 459
.08 1406704047
106 427
.07 1406711038
106 596
.1 1406713111
106 401
.07 1406715872
106 682
.11 1406726192
106 2776
.46 1406726492
105 414
.07 1406728863
105 380
.06 1406734055
105 378
.06 1406734655
105 722
.12 1406735555
105 144
.02 1406665697
105 5
I have edited my answer kindly try the below
SELECT z.no as "ID_One",
max(r.value) as "Max",
round(MAX(r.value)/80000,2) as "ROUND",r.Timestamp
FROM Table1 r, Table2 z
where r.timestamp > ((SYSDATE - TO_DATE ('01/01/1970 00:00:00', 'MM
-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60) - 80000
and r.va=21
AND r.nor IN ('7','98','3','3')
AND r.value=(select max(r1.value) from Table1 r1 where r1.va=r.va and r1.nor=r.nor)
AND r.nor = z.re group by r.nor, r.varr, z.no;
This looks like an ideal use case for analytic functions:
SELECT
v1.*,
round(v1.value/80000,2) as rounded_max_value
FROM (
SELECT
z.no as id_one,
r.value,
row_number() over (partition by r.nor, r.varr, z.no order by r.value desc) as rn,
r.timestamp
FROM Table1 r, Table2 z
WHERE r.timestamp >
((SYSDATE - TO_DATE('01/01/1970 00:00:00', 'MM-DD-YYYY HH24:MI:SS')) * 24 * 60 * 60) - 80000
AND r.va=21
AND r.nor IN ('7','98','3','3')
AND r.nor = z.re
) v1
where v1.rn = 1
This query
uses row_number over (partition by .. order by ) to get an ordering of the rows within a group
uses rn = 1 in the outer query to get only the row having the maximum value
Some additional recommendations:
if your r.nor column is numeric, then don't use string literals; use IN (7,98,3,3) instead (BTW: why do you have 3 twice in your IN list?
don't use " for column aliases unless absolutely necessary (since it makes them case-sensitive) ; they are a PITA
don't put your JOIN conditions into the WHERE clause; it makes your query harder to read. Use ANSI style joins instead.
I have a table something similar to :
ID Value1 Value2
122 800 1600
122 800 1800
133 700 1500
154 800 1800
133 700 1500
188 700 1400
176 900 1500
From this table I want to delete the duplicates (ID of 122 and 133) which have a greater difference between value2 and value1.
This means that where ID is 122 I want to keep the first row (1800-800>1600-800)
This means that where ID is 133 I want to keep either one because they both have the same difference.
ID Value1 Value2
122 800 1600
122 800 1800 <------delete this row
133 700 1500 <------delete either this row or the other identical row
154 800 1800
133 700 1500 <------delete either this row or the other identical row
188 700 1400
176 900 1500
It is on a much larger scale that this, so I cant just individually delete records.
Is there a way to write a statement that will delete all duplicates from my table where Value2 - Value1 is greater than Value2 - Value1 for its duplicate?
SQL Server has this great feature of updatable CTEs and subqueries. So, you can do this as:
with todelete as (
select t.*,
row_number() over (partition by id order by value2 - value1) as diff_seqnum
from table t
)
delete from todelete
where diff_seqnum > 1;
That is, enumerate the rows for each id based on the difference in the two values. Then, only keep the rows where the sequence number is 1.
I previously found the solution to my problem but unfortunately I lost files on my harddrive and I can't find the statement I managed to produce.
I have 2 tables T2REQ and T2STOCK, both have 2 columns (typeID and quantity) and my problem reside in the fact that I can have multiple occurences of SAME typeID in BOTH tables.
What I'm trying to do is SUM(QUANTITY) grouped by typeID and substract the values of T2STOCK from T2REQ but since I have multiple occurences of same typeID in both tables, the SUM I get is multiplied by the number of occurences of typeID.
Here's a sample of T2REQ (take typeID 11399 for example):
typeID quantity
---------- ----------
34 102900
35 10500
36 3220
37 840
11399 700
563 140
9848 140
11486 28
11688 700
11399 390
4393 130
9840 390
9842 390
11399 390
11483 19.5
11541 780
And this is a sample of T2STOCK table :
typeID quantity
---------- ----------
9842 1921
9848 2400
11399 1700
11475 165
11476 27
11478 28
11481 34
11483 122
11476 2
And this is where I'm at for now, I know that the SUM(t2stock.quantity) is affected (multiplied) because of the JOIN 1 = 1 but whatever I tried, I'm not doing it in the right order:
SELECT
t2req.typeID, sum(t2req.quantity), sum(t2stock.quantity),
sum(t2req.quantity) - sum(t2stock.quantity) as diff
FROM t2req JOIN t2stock ON t2req.typeID = t2stock.typeID
GROUP BY t2req.typeID
ORDER BY diff DESC;
typeID sum(t2req.quantity) sum(t2stock.quantity) diff
---------- ------------------- --------------------- ----------
563 140 30 110
11541 780 780 0
11486 28 40 -12
11483 19.5 122 -102.5
9840 390 1000 -610
40 260 940 -680
9842 390 1921 -1531
9848 140 2400 -2260
11399 1480 5100 -3620
39 650 7650 -7000
37 1230 116336 -115106
36 28570 967098 -938528
35 33770 2477820 -2444050
34 102900 2798355 -2695455
You can see that SUM(t2req) for typeID 11399 is correct : 1480
And you can see that the SUM(t2stock) for typeID 11399 is not correct : 5100 instead of 1700 (which is 5100 divided by 3, the number of occurences in t2req)
What would be the best way to avoid multiplications because of multiple typeIDs (in both tables) with the JOIN for my sum substract ?
Sorry for the wall of text, just trying to explain as best as I can since english is not my mother tongue.
Thanks a lot for your help.
You can aggregate before join:
SELECT
t2req.typeID,
t2req.quantity,
t2stock.quantity,
t2req.quantity - t2stock.quantity as diff
FROM
(SELECT TypeID, SUM(Quantity) Quantity FROM t2req GROUP BY TypeID) t2req JOIN
(SELECT TypeID, SUM(Quantity) Quantity FROM t2stock GROUP BY TypeID) t2stock
ON t2req.typeID = t2stock.typeID
ORDER BY diff DESC;
Fiddle sample: http://sqlfiddle.com/#!7/06711/5
You can't do this in a single aggregation:
SELECT
COALESCE(r.typeID, s.typeID) AS typeID,
COALESCE(r.quantity, 0) AS req_quantity,
COALESCE(s.quantity, 0) AS stock_quantity,
COALESCE(r.quantity, 0) - COALESCE(s.quantity, 0) AS diff
FROM (
SELECT rr.typeID, SUM(rr.quantity) AS quantity
FROM t2req rr
GROUP BY rr.typeID
) r
CROSS JOIN (
SELECT ss.typeID, SUM(ss.quantity) AS quantity
FROM t2stock ss
GROUP BY ss.typeID
) s ON r.typeID = s.typeID
ORDER BY 4 DESC;