How to find duplicate rows from three tables using two columns - sql

—oracle sql-
Select *
From Client cl, Contact c, Location l
Where l.locID = c.locID
and cl.clientID = l.clientID
I want to find more than one occurrences(duplicates) using combined columns of locID and clientID

We can use aggregation here:
SELECT cl.clientID, l.locID
FROM Client cl
INNER JOIN Location l ON l.clientID = cl.clientID
INNER JOIN Contact c ON c.locID = l.locID
GROUP BY cl.clientID, l.locID
HAVING COUNT(*) > 1;
Note that I also refactored your query to use explicit joins.
To see all columns, use this version:
WITH cte AS (
SELECT cl.clientID, l.locID, -- add more columns here
COUNT(*) OVER (PARTITION BY cl.clientID, l.locID) cnt
FROM Client cl
INNER JOIN Location l ON l.clientID = cl.clientID
INNER JOIN Contact c ON c.locID = l.locID
)
SELECT *
FROM cte
WHERE cnt > 1;

You can get all the details of the rows using the analytic COUNT function:
SELECT *
FROM (
SELECT cl.clientID,
cl.otherClientColumn,
c.locID,
c.otherContactColumn,
l.otherLocationColumn,
COUNT(*) OVER (PARTITION BY cl.clientID, c.locID) AS num_duplicates
From Client cl
INNER JOIN Contact c
ON (cl.clientID = l.clientID)
INNER JOIN Location l
ON (l.locID = c.locID)
)
WHERE num_duplicates > 1

Related

Take only rows with fields MAX date

I have following query:
SELECT cl.[Name] Client, bt.Name BottleType, SUM(csi.Amount) Amount
FROM T_Clients cl
INNER JOIN T_ClientStore cs ON cs.FK_ClientId = cl.ClientID
INNER JOIN T_ClientStoreItem csi ON csi.FK_ClientStoreId = cs.ClientStoreId
INNER JOIN T_BottleType bt ON bt.BottleTypeId = csi.FK_BootleTypeID
GROUP BY cl.[Name], bt.Name
ORDER BY cl.[Name]
In the T_ClientStore table there is column DueDate. I want to take only the records grouped by cl.[Name] for MAX(DueDate). Where could i define that? Somethin like to add:
WHERE cs.DueDate is MAX
Starting from your existing query and based on your description, a straight-forward approach would be to just turn the join on T_ClientStore to a lateral join, which retrieves the latest record for the given client:
SELECT cl.[Name] Client, bt.Name BottleType, SUM(csi.Amount) Amount
FROM T_Clients cl
CROSS APPLY (
SELECT TOP(1) *
FROM T_ClientStore cs
WHERE cs.FK_ClientId = cl.ClientID
ORDER BY cs.DueDate DESC
) cs
INNER JOIN T_ClientStoreItem csi ON csi.FK_ClientStoreId = cs.ClientStoreId
INNER JOIN T_BottleType bt ON bt.BottleTypeId = csi.FK_BootleTypeID
GROUP BY cl.[Name], bt.Name
ORDER BY cl.[Name]

Select a Row with Max of CreatedOn group by a criteria

select
Container, CreatedOn, *
from
Inventory_container
where
container in (select IC.Container
from INVENTORY_CONTAINER IC
inner join CONTAINER C on IC.Container = C.Container
where C.ContainerClassID = '100000011'
group by IC.Container
having count(IC.Container) >= 2)
Below is the Result of the Query:
As you can see there are similar containers with 2 rows
I want to select the row with the latest createdon.
Please help editing my query.
i think a sub-query and join would help you
select iC.* from INVENTORY_CONTAINER IC inner join
inner join
(
select IC.Container,max(IC.CreatedOn) as CreatedOn
from INVENTORY_CONTAINER IC
inner join CONTAINER C on IC.Container = C.Container
where C.ContainerClassID = '100000011'
group by IC.Container
having count(IC.Container) >= 2
) t on IC.Container=t.Container and IC.CreatedOn=t.CreatedOn
If you are using SQL Server try below query:
SELECT *
FROM (
SELECT *, ROW_NUMBER()OVER(PARTITION BY Container ORDER BY CreatedOn) AS RowNo
FROM INVENTORY_CONTAINER IC INNER JOIN CONTAINER C ON
IC.Container=C.Container
WHERE C.ContainerClassID='100000011'
GROUP BY IC.Container,CreatedOn
HAVING COUNT(IC.Container)>=2
) AS T
WHERE RowNo = 1
You need to write one more subquery to your query.
select
Container,CreatedOn, *
from
Inventory_container
where
container in (select IC.Container
from INVENTORY_CONTAINER IC
inner join CONTAINER C on IC.Container = C.Container
where C.ContainerClassID = '100000011'
and IC.CreatedOn=
(select max(IC1.CreatedOn) from INVENTORY_CONTAINER IC1
where IC1.container=IC.container));
group by IC.Container
having count(IC.Container) >= 2 ;
I am assuming that the query which you have mentioned is syntactically correct as per your DB design.
Try the following query-:
With CTE as
(
SELECT *, ROW_NUMBER()OVER(PARTITION BY Container ORDER BY CreatedOn desc) AS RN
FROM INVENTORY_CONTAINER IC INNER JOIN CONTAINER C ON
IC.Container=C.Container
WHERE C.ContainerClassID='100000011'
GROUP BY IC.Container
HAVING COUNT(IC.Container)>=2
)select * from CTE where RN=1
SQL Server

Finding the count

I have the following SQL query and need to know the count of companyid as I can see repeating data. How do I find the count of it. Following is the query
SELECT a.companyId 'companyId'
, i.orgDebtType 'orgDebtType'
, d.ratingTypeName 'ratingTypeName'
, c.currentRatingSymbol 'currentRatingSymbol'
, c.ratingStatusIndicator 'ratingStatusIndicator'
, g.qualifierValue 'qualifierValue'
, c.ratingdate 'ratingDate'
, h.value 'outlook'
FROM ciqRatingEntity a
JOIN ciqcompany com
on com.companyId = a.companyId
JOIN ciqratingobjectdetail b ON a.entitySymbolValue = b.objectSymbolValue
JOIN ciqRatingData c ON b.ratingObjectKey = c.ratingObjectKey
JOIN ciqRatingType d ON b.ratingTypeId = d.ratingTypeId
JOIN ciqRatingOrgDebtType i ON i.orgDebtTypeId=b.orgDebtTypeId
JOIN ciqRatingEntityData red ON red.entitySymbolValue=a.entitySymbolValue
AND red.ratingDataItemId='1' ---CoName
LEFT JOIN ciqRatingDataToQualifier f ON f.ratingDataId = c.ratingDataId
LEFT JOIN ciqRatingQualifiervalueType g ON g.qualifiervalueid = f.qualifierValueId
LEFT JOIN ciqRatingValueType h ON h.ratingValueId = c.outlookValueId
WHERE 1=1
AND b.ratingTypeId IN ( '130', '131', '126', '254' )
-- and a.companyId = #companyId
AND a.companyId IN
(SELECT distinct TOP 2000000
c.companyId
FROM ciqCompany c
inner join ciqCompanyStatusType cst on cst.companystatustypeid = c.companystatustypeid
inner join ciqCompanyType ct on ct.companyTypeId = c.companyTypeId
inner join refReportingTemplateType rep on rep.templateTypeId = c.reportingtemplateTypeId
inner join refCountryGeo rcg on c.countryId = rcg.countryId
inner join refState rs on rs.stateId = c.stateId
inner join ciqSimpleIndustry sc on sc.simpleIndustryId = c.simpleIndustryId
ORDER BY companyid desc)
ORDER BY companyId DESC, c.ratingdate, b.ratingTypeId, c.ratingStatusIndicator
This will list where there are duplicate companyID's
SELECT companyId, count(*) as Recs
FROM ciqCompany
GROUP BY ciqCompany
HAVING count(*) > 1
I understand that you wish to add a column to the query with the count of each companyId, you can use COUNT() OVER():
select count(a.companyId) over (partition by a.companyId) as companyCount,
<rest of the columns>
from ciqRatingEntity a
join <rest of the query>
This would return in each row the count of the companyId of that row without grouping the results.

How to use a column from joined table in a join with a subquery

What I'm trying to do is this:
SELECT *
FROM MainTable m
INNER JOIN JoinedTable j on j.ForeignID = m.ID
INNER JOIN (SELECT TOP 1 *
FROM SubQueryTable sq
WHERE sq.ForeignID = j.ID
ORDER BY VersionColumn DESC)
So basically, from SubQueryTable, I only want to retrieve a single row which has the maximum value for VersionColumn for all rows with a certain ID that I can get from JoinedTable.
T-SQL doesn't let me do this, what's a good way to solve this problem?
What I'm trying to prevent is loading the entire SubQueryTable and doing the filtering when it's too late as in....
SELECT *
FROM MainTable m
INNER JOIN JoinedTable j on j.ForeignID = m.ID
INNER JOIN (SELECT TOP 1 *
FROM SubQueryTable sq
ORDER BY VersionColumn DESC) sj ON sj.ForeignID = j.ID
I fear this second version performs the very slow subquery first and only filters it when it has loaded all the rows, but I want to filter sooner.
Any thoughts?
This will perform well if you have index on VersionColumn
SELECT *
FROM MainTable m
INNER JOIN JoinedTable j on j.ForeignID = m.ID
CROSS APPLY (SELECT TOP 1 *
FROM SubQueryTable sq
WHERE sq.ForeignID = j.ID
ORDER BY VersionColumn DESC) sj
Answer :
Hi,
Below query I have created as per your requirement using Country, State and City tables.
SELECT * FROM (
SELECT m.countryName, j.StateName,c.CityName , ROW_NUMBER() OVER(PARTITION BY c.stateid ORDER BY c.cityid desc) AS 'x'
FROM CountryMaster m
INNER JOIN StateMaster j on j.CountryID = m.CountryID
INNER JOIN dbo.CityMaster c ON j.StateID = c.StateID
) AS numbered WHERE x = 1
Below is your solution and above is only for your reference.
SELECT * FROM (
SELECT m.MainTablecolumnNm, j.JoinedTablecolumnNm,c.SubQueryTableColumnName , ROW_NUMBER()
OVER(PARTITION BY sj.ForeignID ORDER BY c.sjID desc) AS 'abc'
FROM MainTable m
INNER JOIN JoinedTable j on j.ForeignID = m.ID
INNER JOIN SubQueryTable sj ON sj.ForeignID = j.ID
) AS numbered WHERE abc = 1
Thank you,
Vishal Patel

SQL prestashop stats order total by customers group

I try to export my order total by customers group in prestashop
This is my REQUEST for the group N° 3 for example:
SELECT ROUND(SUM(IFNULL(o.`total_paid_real`, 0 ) / cu.conversion_rate), 2) as totalMoneySpent
FROM `ps_orders` o
LEFT JOIN `ps_currency` cu ON o.id_currency = cu.id_currency
LEFT JOIN `ps_customer` c ON c.id_default_group= 3
WHERE o.valid = 1;
OTHER VERSION (SAME RESULT, the total of all group)
SELECT ROUND( SUM( IFNULL(o.`total_paid_real`, 0 ) / cu.conversion_rate), 2 ) as totalMoneySpent
FROM `ps_orders` o
LEFT JOIN `ps_currency` cu ON o.id_currency = cu.id_currency
#LEFT JOIN `ps_customer` c ON c.id_default_group=3
WHERE o.valid = 1
AND o.id_customer IN( SELECT c.id_customer FROM `ps_customer` c WHERE c.id_default_group=3 )
;
My problem is that c.id_default_group never change the results,
Thanks for your help
SELECT c.group_id, ROUND(SUM(IFNULL(o.`total_paid_real`, 0 ) / cu.conversion_rate), 2) as totalMoneySpent
FROM `ps_orders` o
LEFT JOIN `ps_currency` cu ON o.id_currency = cu.id_currency
Once you apply the aggregate function SUM you have to GROUP BY in order to get the aggregate result for a number of rows (otherwise the aggregate is applied individually for each row, defeating its own purpose).
SELECT c.group_id, ROUND(SUM(IFNULL(o.`total_paid_real`, 0 ) / cu.conversion_rate), 2) as totalMoneySpent
FROM `ps_orders` o
LEFT JOIN `ps_currency` cu ON o.id_currency = cu.id_currency
LEFT JOIN `ps_customer` c ON c.id_default_group= 3
WHERE o.valid = 1
GROUP BY c.group
ORDER BY c.group
assuming group_id identifies the customer group you refer to in the question.