How to get the first row values in sql server query - sql

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

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 use rank/join and where together

I have used multiple inner joins in my code, and I provided rank, but now I want to select a particular rank. So how to use rank in a where statement?
Here is my code, but now please help me to proceed further:
select [YEAR],
[IDManufacturer],
sum([TotalPrice]),
rank() over (order by sum(totalprice) desc) as sales_rank
from [dbo].[DIM_DATE]
join [dbo].[FACT_TRANSACTIONS]
on [dbo].[FACT_TRANSACTIONS].Date = [dbo].[DIM_DATE].DATE
join [dbo].[DIM_MODEL]
on [dbo].[DIM_MODEL].IDModel=[dbo].[FACT_TRANSACTIONS].IDModel
where [YEAR] in (2009,2010)
group by IDManufacturer,[year]
order by sum([TotalPrice]) desc
Now I want to select only rank 3 and 4. How to do that?
You could either do sub-query or CTE, i would suggest try with 2 methods and look at execution plan pick which performs better:
Sub Query
SELECT * FROM
(select [YEAR],
[IDManufacturer],
sum([TotalPrice]) TotalPrice,
rank() over (order by sum(totalprice) desc) as sales_rank
from [dbo].[DIM_DATE]
join [dbo].[FACT_TRANSACTIONS]
on [dbo].[FACT_TRANSACTIONS].Date = [dbo].[DIM_DATE].DATE
join [dbo].[DIM_MODEL]
on [dbo].[DIM_MODEL].IDModel=[dbo].[FACT_TRANSACTIONS].IDModel
where [YEAR] in (2009,2010)
group by IDManufacturer,[year]
) as SQ
Where sales_rank = 3 or sales_rank = 4
go
Common Table Expression
; with CTE as
(select [YEAR],
[IDManufacturer],
sum([TotalPrice]) TotalPrice,
rank() over (order by sum(totalprice) desc) as sales_rank
from [dbo].[DIM_DATE]
join [dbo].[FACT_TRANSACTIONS]
on [dbo].[FACT_TRANSACTIONS].Date = [dbo].[DIM_DATE].DATE
join [dbo].[DIM_MODEL]
on [dbo].[DIM_MODEL].IDModel=[dbo].[FACT_TRANSACTIONS].IDModel
where [YEAR] in (2009,2010)
group by IDManufacturer,[year]
)
SELECT * FROM CTE WHERE sales_rank = 3 or sales_rank = 4
If you want only rank 3 and 4 then try this:
select * from (
select [YEAR],
[IDManufacturer],
sum([TotalPrice]),
rank() over (order by sum(totalprice) desc) as sales_rank
from [dbo].[DIM_DATE]
join [dbo].[FACT_TRANSACTIONS]
on [dbo].[FACT_TRANSACTIONS].Date = [dbo].[DIM_DATE].DATE
join [dbo].[DIM_MODEL]
on [dbo].[DIM_MODEL].IDModel=[dbo].[FACT_TRANSACTIONS].IDModel
where [YEAR] in (2009,2010)
group by IDManufacturer,[year]
order by sum([TotalPrice]) desc
) t where sales_rank in (3,4)
If you only want the 3rd and 4th values -- and assuming no ties -- then use offset/fetch:
offset 2 rows fetch first 2 rows only
The offset 2 is because offset starts counting at 0 rather than 1.

Group row when no serial on serial table

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

SQL HELP getting duplicates when trying to get max(Date) for record

Need some help, here is my SQL below: I am getting duplicates back and it will not return my LastRespondedDate Field. Any help would be greatly appreciated.
SELECT t.[column1],
pr.[column1],
pr.[RespondedDttm],
t.[column2],
t.[column3],
t.[column4]
FROM Table1 t LEFT JOIN
(
SELECT [t.column1], [pr.column2], [RespondedDttm], MAX([RespondedDttm]) AS LastRespondedDate
FROM Table2 pr
GROUP BY [column1], RespondedDttm, [pr.column3]) pr
ON (t.[column1] = pr.[column1])
WHERE t.[column8] IN (value) AND
(pr.[RespondedDttm] >= '2015-09-01') AND
(pr.[Response] IS NOT Null)
SELECT
t.[column1],
pr.[RespondedDttm] as LastRespondedDate,
t.[column2],
t.[column3],
t.[column4]
FROM
Table1 t
LEFT JOIN
(
SELECT
t2.[Column1]
,t2.[column2]
,[RespondedDttm]
,RowNum = ROW_NUMBER() OVER (PARTITION BY ColWithDups ORDER BY [RespondedDttm])
,WithTiesRowNum = RANK() OVER (PARTITION BY ORDER BY [RespondedDttm] DESC)
FROM
Table2 t2
WHERE
t2.[RespondedDttm] >= '2015-09-01'
AND t2.[Response] IS NOT Null
) pr
ON (t.[column1] = pr.[column1])
AND pr.RowNum = 1
--AND pr.WithTiesRowNum = 1 --use this line if you want ties
WHERE
t.[column8] IN (value)
You can use window functions and ROW_NUMBER if you want only 1 row or RANK() if you want all ties.
In case you wanted the other direction of the nuance which I think you comment suggests:
SELECT
t.[column1],
pr.[RespondedDttm] as LastRespondedDate,
t.[column2],
t.[column3],
t.[column4]
FROM
Table1 t
LEFT JOIN
(
SELECT
t2.[Column1]
,t2.[column2]
,[RespondedDttm]
,RowNum = ROW_NUMBER() OVER (PARTITION BY ColWithDups ORDER BY [RespondedDttm])
,WithTiesRowNum = RANK() OVER (PARTITION BY ORDER BY [RespondedDttm] DESC)
FROM
Table2 t2
) pr
ON (t.[column1] = pr.[column1])
AND pr.[RespondedDttm] >= '2015-09-01'
AND pr.[Response] IS NOT Null
AND pr.RowNum = 1
--AND pr.WithTiesRowNum = 1 --use this line if you want ties
WHERE
t.[column8] IN (value)

SQL Server ORDER BY [aggregation] DESC/ASC

I want to be able to sort [comment] by ascending or descending. I've tried performing the aggregation again in the "order by" clause, but that didn't work. I also tried sorting outside of the sub query which let me use the alias [comment], but that only sorted between rows 0 and 10.
This query is a smaller version of a much larger query.
SELECT *
FROM (SELECT ISNULL((SELECT COUNT("order")
FROM order_comment
WHERE "order" = "order"."id"
GROUP BY "order"), 0) AS [comment],
Row_number() OVER (ORDER BY "order"."id" DESC) AS [rownum]
FROM [order]
WHERE ISNULL((SELECT COUNT("order")
FROM order_comment
WHERE "order" = "order"."id"
GROUP BY "order"), 0) > 0) AS [filter]
WHERE [rownum] BETWEEN 0 AND 10
So easy in MySql!
SELECT Ifnull((SELECT COUNT(`order`)
FROM order_comment
WHERE `order` = `order`.`id`
GROUP BY `order`), 0) AS `comment`
FROM `order`
HAVING `comment` > 0
ORDER BY `comment` DESC
LIMIT 0, 10
Following latest edit suspect you want something like this
;WITH oc AS
(
SELECT [order],
COUNT([order]) AS order_count
FROM order_comment
GROUP BY [order]
), occ AS
(
SELECT o.*,
order_count AS comment,
ROW_NUMBER() OVER (ORDER BY order_count DESC) AS [rownum]
FROM [order] o
INNER JOIN oc ON oc.[order] = o.id
)
SELECT *
FROM occ
WHERE [rownum] BETWEEN 0 AND 10
ORDER BY [rownum]
The INNER JOIN will already exclude any rows with no child rows in order_comment
I assume that you don't know that you can use the OVER clause with aggregate functions.
COUNT(order) OVER(PARTITION BY id) AS [comment]
....
ORDER BY [comment]
in SQL Server you can order by column number from your query as in ORDER BY 1
more info here http://blog.sqlauthority.com/2010/12/27/sql-server-order-by-columnname-vs-order-by-columnnumber/
SELECT *
FROM (SELECT ISNULL((SELECT COUNT("order")
FROM order_comment
WHERE "order" = "order"."id"
GROUP BY "order"), 0) AS [comment],
Row_number() OVER (ORDER BY "order"."id" DESC) AS [rownum]
FROM [order]
WHERE ISNULL((SELECT COUNT("order")
FROM order_comment
WHERE "order" = "order"."id"
GROUP BY "order"), 0) > 0) AS [filter]
WHERE [rownum] BETWEEN 0 AND 10
ORDER BY 1