Group row when no serial on serial table - sql

Is it possible to group the SQL query result when the item column has no serial list in serial table? Currently I split the column qty to row so the user can select serial 1 by 1. Here's my query:
SELECT row = ROW_NUMBER() over (ORDER BY t.PARENT), t.PARENT, t.BOMNO, t.COMPONENT, o.Qty, t.UNIT, t.COMPBOMNO, t.ISSERIAL, t.ISLOT
FROM (SELECT ICBOMD.ITEMNO AS [PARENT],
ICBOMD.BOMNO,
ICBOMD.COMPONENT,
ICBOMD.QTY,
ICBOMD.UNIT,
ICBOMD.COMPBOMNO,
ISNULL(ICITEM.SERIALNO, 0) AS [ISSERIAL],
ISNULL(ICITEM.LOTITEM, 0) AS [ISLOT]
FROM ICBOMH LEFT OUTER JOIN
ICBOMD
ON ICBOMH.ITEMNO = ICBOMD.ITEMNO AND ICBOMH.BOMNO = ICBOMD.BOMNO LEFT OUTER JOIN
ICITEM
ON ICITEM.ITEMNO = ICBOMD.COMPONENT
WHERE ICITEM.STOCKITEM = 1 AND ICBOMD.ITEMNO = 'GAM-001' AND ICBOMD.BOMNO = 'P1'
) t CROSS APPLY
(SELECT 1
FROM master..spt_values v
WHERE v.type = 'P' AND v.number < t.QTY
) o(Qty)
For example the COMPONENT GAM-COMP02 has no serial on the serial table. It should be group by and the qty will become 2.
Below query is how I retrieved serial:
SELECT SERIALNUM AS [Serial Number], LOCATION AS [Location],
CONVERT(DATE, CONVERT(VARCHAR, STOCKDATE)) AS [Stock Date], STATUS AS [Available]
FROM ICXSER
WHERE ITEMNUM = 'GAM-COMP02'

You may apply Serial number like that
select row_number() over (order by (select 100)) as Slno, * from table
Note: But this will assign row_number indeterminate ordering.
For this line It should be group by and the qty will become 2. it is better to apply group by.
select COMPONENT , count(COMPONENT) as Count from table group by COMPONENT

Related

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.

How to get the first row values in sql server query

My requirement is AllowedAmount for any latest postdate with latest PaymentID.I have tried many times just to get the firstrow value .But i get 2 rows instead.I tried using rownumber() but its not applicable after selecting for all patient name it doesn't give correct output .Does any one has another method apart from top 1 and rownumber() partition.
My requirement is get One ChargeID with AllowedAmount for the latest Postdate with latest PaymentID
SELECT
DISTINCT
TM.[PatientName] AS [PATIENT NAME],
[dbo].[SplitString](TM.InsPlanName, '(') AS [ Insurance],
ISNULL(TMmm1.ChargeAmount, 0) AS [Amount Billed],
ISNULL(TMM1.AllowedAmount, 0) AS AllowedAmount,
TMM1.PostDate,
TMM1.PaymentID,
TM.ChargeID AS ChargeID
FROM [MasterReport] AS TM
LEFT OUTER JOIN (SELECT
SUM(ISNULL(ChargeAmount, 0)) AS ChargeAmount,
[ChargeID]
FROM [dbo].[TransactionMasterReport]
WHERE transactiontype = 'Charges'
GROUP BY [ChargeID]) AS TMmm1
ON TM.ChargeID = TMmm1.ChargeID
LEFT OUTER JOIN (SELECT DISTINCT
MAX(PostDate) AS PostDate,
MAX(ISNULL(PaymentID, 0)) AS PaymentID,
[ChargeID],
AllowedAmount
FROM [dbo].[TransactionMasterReport]
WHERE ([TransactionType] = 'Payments'
OR [TransactionType] = 'Adjustments')
AND AllowedAmount >= 1
AND PaymentSource LIKE '%Primary%'
GROUP BY [ChargeID],
PostDate,
AllowedAmount,
PaymentID) AS TMM1
ON TM.[ChargeID] = TMM1.[ChargeID]
WHERE TM.ChargeId = 4255
ORDER BY TM.[ChargeID]
When I use top 1 in left outer join I get 0.00 in allowed Amount which is incorrect .
This should work, after you play with it for syntax errors. I do not have tables nor data that match yours. The changes are in the second LeftJoin to use Row_Number ordered by Descending of your fields. You may need to enclose the whole thing in another Select (...) and move the Where RN1 = 1 below that.
SELECT
DISTINCT
TM.[PatientName] AS [PATIENT NAME],
[dbo].[SplitString](TM.InsPlanName, '(') AS [ Insurance],
ISNULL(TMmm1.ChargeAmount, 0) AS [Amount Billed],
ISNULL(TMM1.AllowedAmount, 0) AS AllowedAmount,
TMM1.PostDate,
TMM1.PaymentID,
TM.ChargeID AS ChargeID
FROM [MasterReport] AS TM
LEFT OUTER JOIN (SELECT
SUM(ISNULL(ChargeAmount, 0)) AS ChargeAmount,
[ChargeID]
FROM [dbo].[TransactionMasterReport]
WHERE transactiontype = 'Charges'
GROUP BY [ChargeID]) AS TMmm1
ON TM.ChargeID = TMmm1.ChargeID
LEFT OUTER JOIN (SELECT
PostDate,
ISNULL(PaymentID, 0) AS PaymentID,
ChargeID,
AllowedAmount,
Row_Number() Over(Partition By ChargeID Order By PostDate Desc, PaymentID Desc) as RN1
FROM [dbo].[TransactionMasterReport]
WHERE ([TransactionType] = 'Payments'
OR [TransactionType] = 'Adjustments')
AND AllowedAmount >= 1
AND PaymentSource LIKE '%Primary%'
) AS TMM1
ON TM.[ChargeID] = TMM1.[ChargeID]
WHERE RN1 = 1
and TM.ChargeId = 4255
ORDER BY TM.[ChargeID]
We don't know the actual scenario but as suggested above it should work but as you said it's again returning the same output so use query as a subquery as below and try
To return only one record from the whole output
SELECT TOP 1 *
FROM ( <your query> )
ORDER BY postdate, paymentid DESC
To return top 1 value of each ChargeID
SELECT TOP (1) WITH TIES *
FROM ( <your query> )
GROUP BY ChargeID
ORDER BY postdate, paymentid DESC
I think, you should change your query like,
SELECT TOP 1 <your fields>
FROM [MasterReport] AS TM
LEFT OUTER JOIN <TMmm1> ON TM.ChargeID = TMmm1.ChargeID
LEFT OUTER JOIN <TMM1> ON TM.[ChargeID] = TMM1.[ChargeID]
WHERE TM.ChargeId = 4255
ORDER BY TMM1.PostDate DESC, TMM1.PaymentID DESC
It will give you only one row(TOP 1) and it will be the latest PostDate & PaymentID

Using query result as subquery syntax

I have a table that I need to identify duplicate entries to delete them. I can find the duplicates using the following query
select s.*, t.*
from [tableXYZ] s
join (
select [date], [product], count(*) as qty
from [tableXYZ]
group by [date], [product]
having count(*) > 1
) t on s.[date] = t.[date] and s.[product] = t.[product]
ORDER BY s.[date], s.[product], s.[id]
and then need to use the result from this table to show where [fieldZ] IS NULL
I've tried the following but get error The column 'date' was specified multiple times for 'subquery'.
select * from
(
select s.*, t.*
from [tableXYZ] s
join (
select [date], [product], count(*) as qty
from [tableXYZ]
group by [date], [product]
having count(*) > 1
) t on s.[date] = t.[date] and s.[product] = t.[product]
) as subquery
where [fieldZ] is null
You have column date in your subquery twice because you are selecting s.* and t.*, this will return s.Date and t.date. If you need both columns, alias one of the columns.
You will also run into this problem with the product column. Your subquery cannot return multiple columns with the same name. Only select the columns you need in your subquery instead of selecting all columns. This is a good practice in general and will solve this issue.

Get the rows with first phone number

I need to display 100 members per page. Because of multiple phone numbers of a member, I have to pick the first phone number for each member.
Here is the query which one gets every phone numbers of a member:
SELECT * FROM
(
SELECT
row_number() over(order by(1)) rn,
NAME, PHONE
FROM MEMBERS t0
LEFT OUTER JOIN MEMBER_IDENTITY ON MEMBER_IDENTITY.ID=t0.ID
LEFT JOIN MEMBER_PHONE ON MEMBER_PHONE.MEMBER_ID=t0.ID
WHERE
NAME LIKE 'U%'
ORDER BY NAME ASC
)
WHERE rn >= 0
AND rn <= 100
How can I pick first -or MAX, etc- phone number?
You could make a sub query for retrieving the phone numbers together with their row number per member, and then filter out the first of them:
SELECT *
FROM (
SELECT row_number() OVER (ORDER BY name ASC) rn,
name,
phone
FROM members t0
LEFT JOIN member_identity
ON member_identity.id = t0.id
LEFT JOIN (
SELECT member_id,
phone
row_number() OVER (PARTITION BY member_id ORDER BY (1)) ph_rn
FROM member_phone
) member_phone
ON member_phone.member_id = t0.id
AND ph_rn = 1
WHERE name LIKE 'U%'
ORDER BY name ASC
)
WHERE rn BETWEEN 0 AND 100
I would:
use the same order for determining the rn value as the result set (ORDER BY name ASC), otherwise the order will not be consistent across pages;
use BETWEEN in the outer WHERE condition, although the lower bound condition (0) is not necessary for the first page.
When you switch to MAX you can apply the ROW_NUMBER directly on the name (Windowed Aggregate Functions are calulated after GROUP BY/HAVING):
SELECT * FROM
(
SELECT
row_number() over (ORDER BY NAME ASC) rn,
NAME, MAX(PHONE)
FROM MEMBERS t0
LEFT OUTER JOIN MEMBER_IDENTITY ON MEMBER_IDENTITY.ID=t0.ID
LEFT JOIN MEMBER_PHONE ON MEMBER_PHONE.MEMBER_ID=t0.ID
WHERE NAME LIKE 'U%'
GROUP BY NAME
)
WHERE rn >= 0
AND rn <= 100
or move the aggregation into a Derived Table:
SELECT * FROM
(
SELECT
row_number() over (ORDER BY NAME ASC) rn,
NAME, PHONE
FROM MEMBERS t0
LEFT OUTER JOIN MEMBER_IDENTITY ON MEMBER_IDENTITY.ID=t0.ID
LEFT JOIN
( SELECT MEMBER_ID, MAX(PHONE) AS PHONE
FROM MEMBER_PHONE
GROUP BY NAME
) MEMBER_PHONE
ON MEMBER_PHONE.MEMBER_ID=t0.ID
WHERE NAME LIKE 'U%'
)
WHERE rn >= 0
AND rn <= 100

SQL Server - Compare ordered columns from multiple tables

I have three tables full of item observations, each with say the following columns:
Table2015: ItemName, ItemCount
Table2014: ItemName, ItemCount
Table2013: ItemName, ItemCount
and I'd like to get the 3 highest Counts for each ItemName from Table2015 with a special column that in the report that flags the row if the highest Count for that ItemName in Table2015 is greater than the highest Count for it in Table2014 and Table2013.
I have the following to get the high counts from Table2015, I'm not sure how to proceed to get what I need. Should I use another CTE with the other tables and join it in the final select somehow?
with counts as (
select e.ItemName, e.ItemCount, row_number() over (partition by e.ItemName order by cast(e.ItemCount as int) desc) as rk
from Table2015 e where e.ItemCount <> 'X')
select s.*,
from counts s
where s.rk<4
order by s.ItemName,s.rk;
As long as item names are consistent between years, you just need to join to the other tables
with counts as (
select e.ItemName, e.ItemCount, row_number() over (partition by e.ItemName order by cast(e.ItemCount as int) desc) as rk
from Table2015 e where e.ItemCount <> 'X')
select s.ItemName
, s.ItemCount
, CASE WHEN CAST(t15.ItemCount AS INT) > ISNULL(CAST(t14.ItemCount AS INT), 0) THEN 1 ELSE 0 END AS GreaterThan2014
, CASE WHEN CAST(t15.ItemCount AS INT) > ISNULL(CAST(t13.ItemCount AS INT), 0) THEN 1 ELSE 0 END AS GreaterThan2013
from counts s
inner join counts t15 ON s.ItemName = t15.ItemName and t15.rk = 1
left join (
select ItemName, MAX(CASE WHEN IsNumeric(ItemCount) = 1 THEN CAST(ItemCount AS INT) ELSE -1 END)
from Table2014
where ItemCount <> 'X'
group by ItemName
) t14 on s.ItemName = t14.ItemName
left join (
select ItemName, MAX(CASE WHEN IsNumeric(ItemCount) = 1 THEN CAST(ItemCount AS INT) ELSE -1 END)
from Table2013
where ItemCount <> 'X'
group by ItemName
) t13 on s.ItemName = t13.ItemName
where s.rk<4
order by s.ItemName,s.rk;
Also, you really shouldn't have an 'X' as a possibility in a count field. If you're counting something it should be typed as an INT.