I have laboratory orders system and these orders can be update more than one time for example
order_id test_id update_count
10 1 1
10 1 2
10 1 3
11 2 1
11 5 1
12 3 1
12 3 2
I want to select all orders without duplicates and select orders with maximum update count
I tried a lot and i checked WITH clients as and self join but always select statement returned all rows with all update counts not only maximum update count for each order_id
This is my Select statement:
SELECT LAB_RESULTS.ORDER_ID as 'Order Number'
,LAB_RESULTS.PATIENT_NO as 'Patient No'
,Patients.Patient_Name as 'Patient Name'
,Patients.Age as 'Patient Age'
,LabTests.TestName as 'Test Name'
,LAB_RESULTS.RESULT_NUMBER as 'Result'
,LAB_RESULTS.RESULT_REPORT as 'Text Result'
,LAB_RESULTS.APPROVED_DATE as 'Approved_Date'
,LAB_RESULTS.REQ_FORM_NO as 'Request Form Number'
,LAB_RESULTS.CUSTID as 'Customer Id'
,Machines.Machine_name as 'Machine Name'
,LAB_RESULTS.SAMPLE_ID as 'Sample Id'
,LAB_RESULTS.packageid as 'package id'
,LAB_RESULTS.GROUPID as 'group id'
,LAB_RESULTS.EXAMINED_BY as 'Examined By'
,LAB_RESULTS.EXAMINED_DATE as 'Examined Date'
,LAB_RESULTS.APPROVED_BY as 'Approved By'
,LAB_RESULTS.update_count
FROM LAB_RESULTS
inner join patients on LAB_RESULTS.patient_no = Patients.Patient_No
inner join labtests on LabTests.TestId = LAB_RESULTS.TESTID
inner join Machines on Machines.Machine_id = LAB_RESULTS.machine_id
where LAB_RESULTS.APPROVED_BY is not null
and LAB_RESULTS.SAMPLE_STATUS = 6
and LAB_RESULTS.update_count in (select max(update_count) from LAB_RESULTS where LAB_RESULTS.SAMPLE_STATUS = 6 and LAB_RESULTS.deptid = 2 )
and LAB_RESULTS.deptid = 2
I expect to get the following result :
order_id test_id update_count
10 1 3
11 2 1
11 5 1
12 3 2
then i added this condition but this return only the maximum update count only not group by each order_id only the maximum for all orders.
and LAB_RESULTS.update_count in (select max(update_count) from LAB_RESULTS where LAB_RESULTS.SAMPLE_STATUS = 6 and LAB_RESULTS.deptid = 2 )
How can I do this ?
then i added this condition but this return only the maximum update
count only not group by each order_id only the maximum for all orders.
The only reason your update_count in() didn't work is because you didn't correlate the subquery.
Instead of this:
and LAB_RESULTS.update_count in (
select max(update_count)
from LAB_RESULTS
where LAB_RESULTS.SAMPLE_STATUS = 6
and LAB_RESULTS.deptid = 2
)
You need this:
and LAB_RESULTS.update_count in (
select max(update_count)
from LAB_RESULTS l2
where l2.SAMPLE_STATUS = 6
and l2.deptid = 2
AND l2.order_id=LAB_RESULTS.order_id --correlate to outer query
)
Although I recommend also aliasing the table in the main query and using both aliases in the subquery.
Add this into your select statement:
,DENSE_RANK() OVER
(PARTITION BY LAB_RESULTS.ORDER_ID ORDER BY LAB_RESULTS.update_count DESC) AS rank
Then you will wrap that result in a WITH clause and select and filter doing something like this:
WITH base_query as (
the current query you have with the extra column I suggested before) Select order_id, test_id, update_count where rank=1
CREATE TABLE t1
(order_id INT, test_id INT, update_count INT)
INSERT INTO t1 VALUES
(10,1,1),
(10,1,2),
(10,1,3),
(11,2,1),
(11,5,1),
(12,3,1),
(12,3,2)
SELECT * FROM dbo.t1
SELECT order_id, test_id, MAX(update_count)
FROM dbo.t1
GROUP BY order_id, test_id
ORDER BY order_id, test_id
DROP TABLE dbo.t1
Related
I have following table in T-SQL(there are other columns too but no identity column or primary key column):
Oid Cid
1 a
1 b
2 f
3 c
4 f
5 a
5 b
6 f
6 g
7 f
So in above example I would like to highlight that following Oid are duplicate when looking at Cid column values as "PAIRS":
Oid:
1 (1 matches Oid: 5)
2 (2 matches Oid: 4 and 7)
Please NOTE that Oid 2 match did not include Oid 6, since the pair of 6 has letter 'G' as well.
Is it possible to create a query without using While loop to highlight the "Oid" like above? along with how many other matches count exist in database?
I am trying to find the patterns within the dataset relating to these two columns. Thank you in Advance.
Here is a worked example - see comments for explanation:
--First set up your data in a temp table
declare #oidcid table (Oid int, Cid char(1));
insert into #oidcid values
(1,'a'),
(1,'b'),
(2,'f'),
(3,'c'),
(4,'f'),
(5,'a'),
(5,'b'),
(6,'f'),
(6,'g'),
(7,'f');
--This cte gets a table with all of the cids in order, for each oid
with cte as (
select distinct Oid, (select Cid + ',' from #oidcid i2
where i2.Oid = i.Oid order by Cid
for xml path('')) Cids
from #oidcid i
)
select Oid, cte.Cids
from cte
inner join (
-- Here we get just the lists of cids that appear more than once
select Cids, Count(Oid) as OidCount
from cte group by Cids
having Count(Oid) > 1 ) as gcte on cte.Cids = gcte.Cids
-- And when we list them, we are showing the oids with duplicate cids next to each other
Order by cte.Cids
select o1.Cid, o1.Oid, o2.Oid
, count(*) + 1 over (partition by o1.Cid) as [cnt]
from table o1
join table o2
on o1.Cid = o2.Cid
and o1.Oid < o2.Oid
order by o1.Cid, o1.Oid, o2.Oid
Maybe Like this then:
WITH CTE AS
(
SELECT Cid, oid
,ROW_NUMBER() OVER (PARTITION BY cid ORDER BY cid) AS RN
,SUM(1) OVER (PARTITION BY oid) AS maxRow2
,SUM(1) OVER (PARTITION BY cid) AS maxRow
FROM oid
)
SELECT * FROM CTE WHERE maxRow != 1 AND maxRow2 = 1
ORDER BY oid
I have a question about the Any-Operator.
On Technet it says
For example, the following query finds customers located in a territory not covered by any sales persons.
Use AdventureWorks2008R2;
GO
SELECT
CustomerID
FROM
Sales.Customer
WHERE
TerritoryID <> ANY
(
SELECT
TerritoryID
FROM
Sales.SalesPerson
);
Further
The results include all customers, except those whose sales territories are NULL, because every territory that is assigned to a customer is covered by a sales person. The inner query finds all the sales territories covered by sales persons, and then, for each territory, the outer query finds the customers who are not in one.
But that query returns all customers.
I updated a customers TerritoryID to a value that no sales.person has, but still that query returns all customers, instead of that one I expected ..
Am I missing something ?
Might it be that that article on technet is simply wrong ?
https://technet.microsoft.com/de-de/library/ms187074(v=sql.105).aspx (german)
There is one customer with TerritoryID = 13
Inner query result (SELECT TerritoryID FROM Sales.SalesPerson) :
4
2
4
3
6
5
1
4
6
1
1
6
9
1
8
10
7
And in table Sales.Customer is a row with CustomerID = 13, which is the one not covered by a sales-person..
create table #t1
(
id int
)
insert into #t1
values(1),(2),(3)
As you can see,T1 has three values
now lets see,how Any Works
When 'is Equal to ' is used with any ,it works like IN
select * from #t1 where id=
any(select 0)--no result
when Any is used with > or <> ,Any means get me all the values which are greater than minimum value
select * from #t1 where id<>
any(select 1)--2,3
select * from #t1 where id<>
any(select 0)--1,2,3
If your subquery returns one value,the outer query will try to get values which are greater than inner query
<> ANY means any Sales.Customer with a TerritoryID that is Greater Than or Less Than any of the TerritoryID's in the Sales.SalesPerson
so TerritoryID = 13 is greater than all or your examples (4 2 4 3 6 5 1 4 6 1 1 6 9 1 8 10 7), so it's included.
<> ALL is the equivalent of NOT IN so that is what you're confusing <> ANY with
Look at <> ANY as, if there are any records in the set that are not equal to the quailifier, then include it.
The following query has the same result:
SELECT CustomerID FROM Sales.Customer
WHERE TerritoryID NOT IN (SELECT TerritoryID FROM Sales.SalesPerson)
I need the count of rows after the group by.
SELECT COUNT(CheckNumber)
FROM myTable
WHERE Status = 'Good'
GROUP BY CheckNumber
Results:
Row 1 = 1
Row 2 = 15
Row 3 = 5
I also tried using DISTINCT
SELECT COUNT(DISTINCT CheckNumber)
FROM myTable
WHERE Status = 'Good'
GROUP BY CheckNumber
Results:
Row 1 = 1
Row 2 = 1
Row 3 = 1
I want the results to be 3
It seems to me the GROUP BY is entirely redundant based on what you say you want. Why not just:
SELECT COUNT(distinct CheckNumber)
FROM myTable
WHERE Status = 'Good'
If I understand correctly you could do this:
SELECT COUNT(*) FROM
(
SELECT COUNT(CheckNumber)
FROM myTable
WHERE Status = 'Good'
GROUP BY CheckNumber
) as myData
This should give you your total of 3 as requested.
I need to find the missing rows that exist in a table of our SQL Server. I have a list of 3 items, for example, that must always exist for each header_id as individual rows with the appropriate product_id.
So ideally the data should be appear as this:
header_id product_id product_group_id
10 Main Product 7
10 Bundle Item 1 50
10 Bundle Item 2 50
10 Bundle Item 3 50
However, due to the process in which the information is added to the database it requires each line to be added individually by the data entry person. As a result we are seeing values such as this where "Bundle Item 2" is missing:
header_id product_id product_group_id
10 Main Product 7
10 Bundle Item 1 50
10 Bundle Item 3 50
The following script displays the header_id's that are missing a missing product_id however it only provides the product_id of "Main Product".
SELECT header_id, product_id, product_group_id
FROM Table1
WHERE
(product_id = 'Main Product')
AND (header_id NOT IN (SELECT product_id
FROM table1 AS table1_1
WHERE (product_id = 'Bundle Item 2')))
I know I can use unions to group multiple queries and force a description value such as this below but would prefer an alternative way if possible.
SELECT header_id, product_id, product_group_id, 'Bundle Item 2' as Description
FROM Table1
WHERE
(product_id = 'Main Product')
AND (header_id NOT IN (SELECT product_id
FROM table1 AS table1_1
WHERE (product_id = 'Bundle Item 2')))
UNION
SELECT header_id, product_id, product_group_id, 'Bundle Item 3' as Description
FROM Table1
WHERE
(product_id = 'Main Product')
AND (header_id NOT IN (SELECT product_id
FROM table1 AS table1_1
WHERE (product_id = 'Bundle Item 3')))
yup,you hv to redesign your DB.There can be so many data namely anything.how do i know under which main product id comes what all sub product id.and if anything is missing .I cannot hard code 'Bundle Item 2'.
If each main product will have at least 3 sub product then using row_number you can find...what ?
Declare #t table (header_id int,product_id varchar(50),product_group_id int)
insert into #t
select 10, 'Main Product', 7 union all
select 10, 'Bundle Item 1' , 50 union all
select 10, 'Bundle Item 2' , 50 union all
select 10, 'Bundle Item 3' , 50
select *,row_number()over(order by product_id)rn from #t where product_group_id<>7
If you know you need exactly those four products, then you can handle this by creating all possible combinations of header_id and product. Then use left outer join to find the ones that are missing:
with prods as (
select 'Main Product' as product union all
select 'Bundle Item 1' union all
select 'Bundle Item 2' union all
select 'Bundle Item 3'
),
allheaderprods as (
select distinct header_id, product
from prods cross join
table1
)
select ahp.*
from allheaderprocs ahp left outer join
header h
on ahp.header_id = h.header_id and
ahp.product = h.product
where ahp.header_id is null;
I have an MSSQL 2000 table that has a lot of duplicate entries. Each row has an EffectiveChange data column. I want to get the most up to date row by getting the row with the max(EffectiveChange) for each key value.
This is some sample data:
NPANXX TZONE EFFCHANGE RATE
555555 1 01/01/09 1
555555 1 05/01/09 6
214555 2 01/01/09 1
214555 2 05/01/09 3
657555 3 05/01/09 1
657555 1 01/01/09 1
I came up with this:
SELECT DISTINCT
NPANXX,
TZONE,
RATE
FROM AreaCodes
INNER JOIN (SELECT DISTINCT NPANXX, EFFCHANGE FROM AREACODES) b
ON b.NPANXX = AreaCodes.NPANXX
GROUP BY
NPANXX,
TZONE,
RATE
HAVING AreadCodes.EFFCHANGE = max(b.EFFCHANGE)
My question is whether or not this query will give me the max EFFCHANGE row for each key (NPANXX) or will it only give me rows having the MAX(EFFCHANGE) for the whole table?
one way since you are using 2000 in 2005 and up you can also use row_number()
SELECT t1.*
from AreaCodes t1
INNER JOIN (SELECT NPANXX, max(EFFCHANGE) as MaxDate FROM AREACODES
group by NPANXX) t2
ON t1.NPANXX = t2.NPANXX
and t1.EFFCHANGE = t2.MaxDate
here is the complete code including DML and DDL
create table AreaCodes(NPANXX int,TZONE int,EFFCHANGE datetime,RATE int)
insert AreaCodes values(555555,1,'20090101',1)
insert AreaCodes values(555555,1,'20090501',6)
insert AreaCodes values(214555,2,'20090101',1)
insert AreaCodes values(214555,2,'20090501',3)
insert AreaCodes values(657555,3,'20090501',1)
insert AreaCodes values(657555,1,'20090101',1)
SELECT t1.*
from AreaCodes t1
INNER JOIN (SELECT NPANXX, max(EFFCHANGE) as MaxDate FROM AREACODES
group by NPANXX) t2
ON t1.NPANXX = t2.NPANXX
and t1.EFFCHANGE = t2.MaxDate
output
657555 3 2009-05-01 00:00:00.000 1
555555 1 2009-05-01 00:00:00.000 6
214555 2 2009-05-01 00:00:00.000 3