SQL Getting the total or sum of a column - oracle

So here's the query that I currently have.
`SELECT war.id, inv.pro_id, inv.quantity
FROM L4_Warehouses war, L4_Inventories inv, L4_Employees emp, L4_Orders ord
WHERE inv.war_id = war.id AND
war.id = emp.war_id AND
emp.id = ord.emp_id AND
ord.status = 'P'
ORDER BY inv.war_id, inv.pro_id;`
this query gives this table.
Now, what I want to get for the final result is to get the sum of those Quantities, example below
ID PRO_ID QUANTITY
1 100 18
1 101 6
1 110 6

Try SUM and GROUP BY:
SELECT war.id, inv.pro_id, SUM(inv.quantity)
FROM L4_Warehouses war, L4_Inventories inv, L4_Employees emp, L4_Orders ord
WHERE inv.war_id = war.id AND
war.id = emp.war_id AND
emp.id = ord.emp_id AND
ord.status = 'P'
GROUP BY war.id, inv.pro_id
ORDER BY inv.war_id, inv.pro_id;

Related

Return duplicate min values

See the table below for reference. I need to return duplicate rows containing the min value.
In this example I want to show only the 2 rows that have SLAT_LEN = 30 or rather the min SLAT_LEN. I tried rank but when I do it does a consecutive rank. I want the duplicate sizes to have the same rank and to rank consecutively by size.
The sizes change so I can't just use a condition like SLAT_LEN = 30.
Or is there a different approach that I should take?
select *
from(
select lg.wd_demand_id,wm.slat_len, wm.prof_size, wm.wd_material_id, wm.color, rank() over ( partition by wm.slat_len order by lg.wd_demand_id) as rank
from wd_demand_log lg, wd_bins wb, wd_material wm, wd_bins_material wbm
where lg.wd_bins_id = wb.wd_bins_id
and lg.wd_material_id = wm.wd_material_id
and lg.wd_bins_id = wbm.wd_bins_id
and lg.wd_material_id = wbm.wd_material_id
AND lg.plant_id = 44 AND lg.dept_id = 220 AND wb.plant_id = 44 AND wb.dept_id = 220
AND NOT EXISTS(SELECT dmpln.wd_demand_id FROM wd_demnd_pln_inv dmpln WHERE dmpln.wd_demand_id = lg.wd_demand_id)
AND wm.prof_size = '2' AND wm.color = 450
AND lg.wd_po_error is null)
You'd use PARTITION BY to give the range in which to rank. The ORDER BY specifies the ranking. So in your case you'll need something like
rank() over (order by wm.slat_len)
In case you have Oracle 12c you can limit your results with FETCH FIRST:
ORDER BY wm.slat_len
FETCH FIRST 1 ROW WITH TIES;
Perhaps I am not understanding the problem correctly, but here is my potential solution:
WITH aset
AS (SELECT lg.wd_demand_id
, wm.slat_len
, wm.prof_size
, wm.wd_material_id
, wm.color
FROM wd_demand_log lg, wd_bins wb, wd_material wm
, wd_bins_material wbm
WHERE lg.wd_bins_id = wb.wd_bins_id
AND lg.wd_material_id = wm.wd_material_id
AND lg.wd_bins_id = wbm.wd_bins_id
AND lg.wd_material_id = wbm.wd_material_id
AND lg.plant_id = 44
AND lg.dept_id = 220
AND wb.plant_id = 44
AND wb.dept_id = 220
AND NOT EXISTS
(SELECT dmpln.wd_demand_id
FROM wd_demnd_pln_inv dmpln
WHERE dmpln.wd_demand_id = lg.wd_demand_id)
AND wm.prof_size = '2'
AND wm.color = 450
AND lg.wd_po_error IS NULL)
SELECT *
FROM aset
WHERE slat_len = (SELECT MIN (slat_len)
FROM aset)

Oracle 11g Count query slowness

I have written one query which provides me a count of item type using group by.
The select query if I fire without group up and count provides results in less than a second on sql developer.
However count query runs for ever that I have to kill the process.
Below is the query ..
WITH permList
AS (SELECT user_perm_level,
item_category,
active
FROM usr_perm_levels
WHERE usr_pk = '7'
UNION ALL
SELECT home_key,
'ALL',
0
FROM user_home_list
WHERE usr_pk = 7
UNION ALL
SELECT home_key,
'UYT',
0
FROM user_home_list
WHERE usr_pk = 7
UNION ALL
SELECT home_key,
'ABR',
0
FROM user_home_list
WHERE usr_pk = 7),
list1
AS (SELECT a.parent_home_key,
b.item_category
FROM user_hier a
INNER JOIN indhome b
ON a.child_home_key = b.user_perm_level),
list2
AS ((SELECT oh.child_home_key,
u.item_category
FROM indhome U
INNER JOIN user_hier oh
ON u.user_perm_level = oh.parent_home_key
AND u.active = 1)
UNION ALL
SELECT user_perm_level,
item_category
FROM indhome)
SELECT type,
Count(*)
FROM inventory
WHERE is_available = 0
AND active = 1
AND EXISTS (SELECT 0
FROM inventory_auth c
WHERE EXISTS (SELECT 0
FROM orglist1
WHERE c.user_perm_level = orglist1.parent_home_key
AND c.item_category =
orglist1.item_category
AND c.active = 1)
OR EXISTS (SELECT 0
FROM orglist2
WHERE c.user_perm_level = orglist2.child_home_key
AND c.item_category =
orglist2.item_category)
AND inventory.item_key = c.item_key
AND inventory.item_category = c.item_category)
GROUP BY type;
In explain plan I see that Cost of group by clause is 145297221173.
Now here inventory table has 10 million records and the exists block which works around inventory table also runs into 15 million records.
Where as views permList, list1 and list2 have records only in 100s.
I have tried various combination but none of them seems to bring better performance. Such as I have tried inner join between inventory and inner query with exists clause but that doesn't help much.

rownum and group by to limit to 1000 rows in detail

I need to limit to 1000 rows in detail table EL8_STGG_CEHL_EXCP for each unique combination keys(AST_ID,PRCS_ID,PRCS_NME,PRCS_STEP_NME,SRC_APPL_LOG_DT) in the EL8_STGG_CEHL_LOG.
For example - If there are 3 unique combination keys, I expect 3000 rows in the detail table.
SELECT
E.AST_ID,
E.PRCS_ID,
E.PRCS_NME,
E.PRCS_STEP_NME,
E.SRC_APPL_LOG_DT
FROM EL8_STGG_CEHL_EXCP E,EL8_STGG_CEHL_LOG L
WHERE
L.AST_ID = E.AST_ID
AND L.PRCS_ID = E.PRCS_ID
AND L.PRCS_NME = E.PRCS_NME
AND L.PRCS_STEP_NME = E.PRCS_STEP_NME
AND L.SRC_APPL_LOG_DT = E.SRC_APPL_LOG_DT
AND (L.CEHL_PICK_UP_IND IS NULL OR UPPER(L.CEHL_PICK_UP_IND) not in ('Y','P'))
GROUP BY
E.AST_ID,
E.PRCS_ID,
E.PRCS_NME,
E.PRCS_STEP_NME,
E.SRC_APPL_LOG_DT
it would be great help if anyone can help me out
Thanks
Untested... that's a lot of data to mock up.
Basically, I use my favorite analytic function, row_number()
with limited as (
select
L.*,
row_number() over (partition by AST_ID,PRCS_ID,PRCS_NME,
PRCS_STEP_NME,SRC_APPL_LOG_DT order by rownum) as rn
from EL8_STGG_CEHL_LOG L
)
SELECT
E.AST_ID,
E.PRCS_ID,
E.PRCS_NME,
E.PRCS_STEP_NME,
E.SRC_APPL_LOG_DT
FROM
EL8_STGG_CEHL_EXCP E,
limited L
WHERE
L.AST_ID = E.AST_ID
AND L.PRCS_ID = E.PRCS_ID
AND L.PRCS_NME = E.PRCS_NME
AND L.PRCS_STEP_NME = E.PRCS_STEP_NME
AND L.SRC_APPL_LOG_DT = E.SRC_APPL_LOG_DT
AND L.RN <= 1000
AND (L.CEHL_PICK_UP_IND IS NULL OR UPPER(L.CEHL_PICK_UP_IND) not in ('Y','P'))

Need to convert this query to linq or lambda

This query pulls back two columns a userid column and a column of their total sales for the current month.
I need to add a column that ranks them (it would be the exact same as the row #)
And I need to convert this from SQL to LINQ or Lambda.
select pu.userID, SUM(o.OrderTotal) as OrderTotal from ProPit_User pu
inner join SeperateDB.dbo.orders o on pu.salesrepid = o.salesrepid and o.DateCompleted > '2014-05-01' and o.DateCompleted < '2014-05-23'
group by pu.userID
order by SUM(o.OrderTotal) desc
Currently returns:
userID OrderTotal
340 68992.74
318 49575.05
228 42470.88
278 38196.87
291 36220.52
351 34962.32
422 31764.67
178 31433.41
430 30836.77
212 30375.99
To capture the ranking index using SQL, you can simply modify your current sql as such:
SELECT pu.userid,
SUM(o.OrderTotal) AS OrderTotal,
ROW_NUMBER() OVER (ORDER BY SUM(o.ordertotal) DESC) AS [Rank]
FROM ProPit_User pu
INNER JOIN SeperateDB.dbo.Orders o ON pu.salesrepid = o.salesrepid
AND o.DateCompleted > '2014-05-01' AND o.DateCompleted < '2014-05-23'
GROUP BY pu.userid
ORDER BY SUM(o.OrderTotal) DESC
which will yield
userID OrderTotal Rank
340 68992.74 1
318 49575.05 2
228 42470.88 3
etc
Not sure in which context you want to 'convert to LINQ'. If you mean a linq query against these two tables within an EF or Linq-to-Sql context, then these statements will yield the same results as above:
var minDate = new DateTime(2014,5,1);
var maxDate = new DateTime(2014,5,23);
-- the linq to sql query:
-- join on salesrepid, group by userid, sum the ordertotals
var dbQuery = ProPit_Users.GroupJoin(
Orders,
pu => pu.salesrepid,
o => o.salesrepid,
(pu, orders) => new
{
pu.UserId,
OrderTotal = orders.Where(o => o.datecompleted > minDate && o.datecompleted. < maxDate )
.Sum(o => o.ordertotal)
}
)
.OrderByDescending(row => row.OrderTotal)
-- materialize the db query
.ToList();
-- add ranking to the results of the query
var userRankings = dbQuery.Select((row, idx) => new { Rank = ++idx, row.UserId, row.OrderTotal });
which will yield a list of objects:
Rank UserID OrderTotal
1 340 68992.74
2 318 49575.05
3 228 42470.88
etc

How to get the last element by date of each "type" in LINQ or TSQL

Imagine to have a table defined as
CREATE TABLE [dbo].[Price](
[ID] [int] NOT NULL,
[StartDate] [datetime] NOT NULL,
[Price] [int] NOT NULL
)
where ID is the identifier of an action having a certain Price. This price can be updated if necessary by adding a new line with the same ID, different Price, and a more recent date.
So with a set of a data like
ID StartDate Price
1 01/01/2009 10
1 01/01/2010 20
2 01/01/2009 10
2 01/01/2010 20
How to obtain a set like the following?
1 01/01/2010 20
2 01/01/2010 20
In SQL, there are several ways to say it. Here's one that uses a subquery:
SELECT *
FROM Price p
WHERE NOT EXISTS (
SELECT *
FROM Price
WHERE ID = p.ID
AND StartDate > p.StartDate
)
This translates fairly trivially to LINQ:
var q = from p in ctx.Price
where !(from pp in ctx.Price
where pp.ID == p.ID
&& pp.StartDate > p.StartDate
select pp
).Any()
select p;
Or should I say, I think it does. I'm not in front VS right now, so I can't verify that this is correct, or that LINQ will be able to convert it to SQL.
Minor quibble: Don't use the name ID to store a non-unique value (the type, in this case). It's confusing.
Assuming ID & StartDate will be unique:
SELECT p.ID, p.StartDate, p.Price
FROM Price p
JOIN
(
SELECT ID, MAX(StartDate) AS LatestDate
FROM Price
GROUP BY ID
) p2 ON p.ID = p2.ID AND p.StartDate = p2.LatestDate
Since you tagged your question with LINQ to SQL, here is an LINQ query to express what you want:
from price in db.Prices
group price by price.Id into group
let maxDateInGroup = group.Max(g => g.StartDate)
let maxDatePrice = group.First(g => g.StartDate == maxDateInGroup)
select
{
Id = group.Key,
StartDate = maxDatePrice.StartDate,
Price = maxDatePrice.Price
};

Resources