Getting more details out of a SQL subquery - sql

I have a SQL Query giving me a list of double records in my database.
select periodid, itemid from periodscore
group by periodid, itemid
having count(*) > 1
This works as expected, but now I would like to retrieve additional fields of these records (such as date last updated etc). So I tried:
select * from periodscore where periodscoreid in
(select periodscoreid from periodscore
group by periodid, itemid
having count(*) > 1)
Of course this doesn't work and gives me the error:
Column 'periodscore.PeriodScoreID' is
invalid in the select list because it
is not contained in either an
aggregate function or the GROUP BY
clause.
How can I retrieve the extra fields in this query?

select ps.*
from periodscore ps
inner join (
select periodid, itemid
from periodscore
group by periodid, itemid
having count(*) > 1
) psm on ps.periodid = psm.periodid and ps.itemid = psm.itemid

select p1.* from periodscore p1 JOIN
(select periodid, itemid from periodscore
group by periodid, itemid
having count(*) > 1) p2
ON (p1.periodId = p2.periodId
AND p1.itemid = p2.itemid)
if periodid or item have null values then
select p1.* from periodscore p1 JOIN
(select periodid, itemid from periodscore
group by periodid, itemid
having count(*) > 1) p2
ON (IFNULL(p1.periodId,0) = IFNULL(p2.periodId,0))
AND IFNULL(p1.itemid,0) = IFNULL(p2.itemid,0))

Related

Convert rows to columns and sum with group by

I have a table with columns ID, WorkingDate and AmountReceived where data is show as
ID WorkingDate AmountReceived
-------------------------------------
1 13/April/2021 201999.01
2 14/Arpil/2021 1099.02
Now, I am trying to show it like
13/April/2021 14/April/2021 15/April/2021
--------------------------------------------------
201999.01 1099.02 102.09
I tried this
select AmountReceived, WorkingDate
from Orders o
select distinct o.WorkingDate, sum(AmountReceived) over (partition by WorkingDate) as total
from Orders o
group by WorkingDate, AmountReceived
But it throws an aggregate error.
Using PIVOT operator, you can achieve what you want
select *
from
(
select o.WorkingDate, o.AmountReceived
from Orders o
) o
pivot
(
sum(AmountReceived)
for WorkingDate in ([2021-04-13], [2021-04-14], [2021-04-15])
) p

SQL MAX in two columns by statistic

I have this query:
DECLARE #startTime DATETIME = DATEADD(MINUTE, -100, GETDATE()) --StartTime
SELECT
COUNT(*) Frecuency, mes.receivedqty AS Qty, ac.item AS Item
FROM
mesReservationReceipts mes (nolock)
INNER JOIN
ACCS_Reservation ac (nolock) ON ac.IDReservation = mes.idReservation
WHERE
ac.item IN (SELECT ac2.item
FROM mesReservationReceipts m2
INNER JOIN ACCS_Reservation ac2 ON ac2.IDReservation = m2.idReservation
WHERE m2.receivedate > #startTime)
GROUP BY
mes.receivedqty, ac.item
I get this result, but only I want the yellow highlighted rows - how can I get those? Please help!:
Note: I tried with MAX(Frequency) but that does not work because it should be grouped by the qty, and its the same case. I put a MAX(Qty), but for example, if the Qty is more than Statistic, add in the table result (and I only want the real statistic qty).
You can write something like this
SELECT * FROM(SELECT Frequency,Receivedqty,Item,
ROW_NUMBER() OVER(Partition by Item ORDER BY Quantity desc) as RowId
FROM (
----your query-----
))as q
Where q.RowId = 1
You can use row_number() to get the highest amount in each column. Then filter:
select item, Frecuency, qty
from (select ac.item as Item, count(*) as Frecuency, mes.receivedqty as Qty,
row_number() over (order by count(*) desc) as seqnum_f,
row_number() over (order by mes.receivedqty desc) as seqnum_r
from mesReservationReceipts mes join
ACCS_Reservation ac
on ac.IDReservation = mes.idReservation
where ac.item in (select ac2.item
from mesReservationReceipts m2 inner join
ACCS_Reservation ac2
on ac2.IDReservation = m2.idReservation
where m2.receivedate > #startTime
)
group by mes.receivedqty, ac.item
) ma
where 1 in (seqnum_f, seqnum_r);
Use rank() if you want duplicates, in the event that the highest values have duplicates.

SQL max function with another condition not working

This works perfectly until an order comes in where the stationID is not =2. My logic would be that sql searches where both conditions meet and display those results and not look where timeplaced is max then if stationid does not =2 display nothing which is what its doing.
SELECT OrderNo
FROM Orders
WHERE TimePlaced = (SELECT max(TimePlaced) FROM Orders)
AND StationID=2
Add your condition into the inner select too
SELECT OrderNo
FROM Orders
WHERE TimePlaced =
(
SELECT max(TimePlaced)
FROM Orders
WHERE StationID=2
)
AND StationID=2
But if you do not want to add the condition twice, then just "link" the inner select with the outer:
SELECT OrderNo
FROM Orders O
WHERE TimePlaced =
(
SELECT max(TimePlaced)
FROM Orders
WHERE StationID=O.StationID
)
AND StationID=2
Another way you could try would be with using a CTE and ROW_NUMBER:
;WITH OrdersCTE AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY StationID ORDER BY TimePlaced Desc) AS rn
FROM Orders
)
SELECT *
FROM OrdersCTE
WHERE rn = 1
AND StationID = 2

SQL Query not fetching correct results

Can somebody please give me the correct query.
I have a table Item with two columns ItemNo and AliasItemNo.
I want to write a query to return me only those items that have more than one alias name
I'm trying to execute
select ItemNo, AliasItemNo
from Item
group by ItemNo, AliasItemNo
having count(ItemNo) > 1
order by ItemNo Asc
This query is not giving correct results.
Pls help
A subquery with the count is the way that works in all rdbms:
SELECT ItemNo, AliasItemNo FROM Item i1
WHERE (SELECT COUNT(*) FROM Item i2 WHERE i1.ItemNo=i2.ItemNo) > 1
ORDER BY ItemNo Asc
In SQL-Server >= 2005 you could also use COUNT(*) OVER (PARTITION BY ItemNo) in a CTE:
WITH CTE AS(
SELECT ItemNo,AliasItemNo,
Num=COUNT(*) OVER (PARTITION BY ItemNo)
FROM Item)
SELECT ItemNo, AliasItemNo FROM CTE
WHERE Num > 1
ORDER BY ItemNo Asc;
Demo: http://sqlfiddle.com/#!6/78d9c/9/1
This should work:
select ItemNo
from Item
group by ItemNo
having count(AliasItemNo) > 1
order by ItemNo Asc
You are counting ItemNo instead of AliasItemNo
There are a lot of ways to do this. Here's a couple of ways.
--using a sub query
SELECT
ItemNo,
AliasItemNo
FROM
Item INNER JOIN
(
SELECT
ItemNo
GROUP BY
ItemNo
HAVING
COUNT(AliasItemNo) > 1)
AS dupes
ON
Item.ItemNo = dupes.ItemNo
ORDER BY
Item.ItemNo ASC
--using CTE
;WITH
dupes AS
(
SELECT
ItemNo
GROUP BY
ItemNo
HAVING
COUNT(AliasItemNo) > 1
)
SELECT
ItemNo,
AliasItemNo
FROM
Item INNER JOIN dupes
ON
Item.ItemNo = dupes.ItemNo
ORDER BY
Item.ItemNo ASC

How to add values coming from 2 queries

From the 1st query I am getting some value and from 2nd query I am getting some value. I want the sum of the two values.
Query 1:
select sum(EAmount) from EstimateAmount where pid='3' group by pid
Query 2:
select sum(OPEAmount) from OPEAmount where pid='3' group by pid
select
(select sum(EAmount) from EstimateAmount
where pid='3'
group by pid)
+
(select sum(OPEAmount) from OPEAmount
where pid='3'
group by pid)
Mitch solution is correct, I just want to add a more generic one for the cases when you need the sum for all pids and that can be extended to more aggregates:
with agg_EA as (
select pid, sum(EAmount) as sumEA
from EstimateAmount
group by pid)
, agg_OPEA as (
select pid, sum(OPEAmount) as sumOPE
from OPEAmount
group by pid)
select sumEA+sumOPE
from agg_EA
join agg_OPEA on agg_EA.pid = agg_OPE.pid
You can also use Union All and within a nested table when aggregating sums of sums
select sum(agg.Total) as GrandTotal
from ( select sum(EAmount) as Total from EstimateAmount where pid='3' group by pid
union all
select sum(OPEAmount) as Total from OPEAmount where pid='3' group by pid
) agg
Just join them:
SELECT sum(coalesce(e.EAmount,0) + coalesce(o.OPEAmount,0))
FROM EstimateAmount e
LEFT JOIN OPEAmount o ON o.pid = e.pid
WHERE e.pid = 3
GROUP BY e.pid