Delete Duplicates per Account NO in SQL Server Manager - duplicates

I have a table called CAL (is a table that holds notes per customer account). At some point an import process added 265 duplicates notes per acct_no, where i need to delete all but 1 per acct_no.
I am able to pull the query to find the duplicates but don't know how to delete duplicates per acct_No while keeping at least 1 record per acct_no
SELECT ACCT_NO, [TYPE], DATE_ADDED, TIME_ADDED, ADDED_BY, NOTES, COUNT(*)
FROM PLSHARED.DBO.CAL
GROUP BY ACCT_NO, [TYPE], DATE_ADDED, TIME_ADDED, ADDED_BY, NOTES
HAVING COUNT(*) > 10
ORDER BY ACCT_NO
Sample Results are:
ACCT_NO TYPE TIME_ADDED ADDED_BY NOTES COUNT
100224 ~APPAACOLC 2019-04-23 11:35:00 APPAA phone : 6463736300 result : LEFT MESSAGE 265
100299 ~APPAACOLC 2019-04-23 11:36:00 APPAA phone : 6462793975 result : ANSWERED 265
100361 ~APPAACOLC 2019-04-23 11:35:00 APPAA phone : 9178863391 result : ANSWERED 265
100630 ~APPAACOLC 2019-04-23 11:36:00 APPAA phone : 5164663631 result : LEFT MESSAGE phone : 5166623996 result : ANSWERED 265
101546 ~APPAACOLC 2019-04-23 11:37:00 APPAA phone : 5163651466 result : ANSWERED 265
101809 ~APPAACOLC 2019-04-23 11:37:00 APPAA phone : 9176985008 result : ANSWERED 265
102239 ~APPAACOLC 2019-04-23 11:37:00 APPAA phone : 9174406128 result : LEFT MESSAGE 265

figured it out, here is the proper code:
WITH Duplicates_CTE(ACCT_NO, [TYPE], DATE_ADDED, TIME_ADDED, ADDED_BY, NOTES, U_INVNO, recno)
AS
(
SELECT ACCT_NO, [TYPE], DATE_ADDED, TIME_ADDED, ADDED_BY, NOTES, U_INVNO,Min(recno) recno
FROM PLSHARED.DBO.cal
GROUP BY ACCT_NO, [TYPE], DATE_ADDED, TIME_ADDED, ADDED_BY, NOTES,U_INVNO
HAVING Count(*) > 3)
DELETE FROM PLSHARED.DBO.cal
WHERE recno IN (
SELECT cal.recno
FROM PLSHARED.DBO.cal
INNER JOIN Duplicates_CTE
ON cal.ACCT_NO = Duplicates_CTE.ACCT_NO
and cal.[TYPE] = Duplicates_CTE.[TYPE]
and cal.DATE_ADDED = Duplicates_CTE.DATE_ADDED
and cal.TIME_ADDED = Duplicates_CTE.TIME_ADDED
and cal.ADDED_BY = Duplicates_CTE.ADDED_BY
and cal.NOTES = Duplicates_CTE.NOTES
and cal.U_INVNO = Duplicates_CTE.U_INVNO
AND cal.recno <> Duplicates_CTE.recno
)

Related

Sum unequal and removing duplicates from SQL query results

My base query:
SELECT project_id
name
stories_produced
on_date
FROM project_prod
WHERE on_date IN ('2017-03-01', '2017-06-10')
ORDER BY project_id
It can get me these outputs:
Output example:
id name stories_produced on_date
1042 project 1 1001 (wanted) 2017-03-01
1042 project 1 1801 (wanted) 2017-06-10
1568 project 2 355 (wanted) 2017-06-10
1405 project 3 1 (not wanted) 2017-03-10
1405 project 3 1 (not wanted) 2017-06-10
Obs: There is a constraint on (id, on_date) meaning there can always be only one record of a project production on a specific date.
Duplicate records, that have the same id, and exist in both dates and have different production values (wanted)
Single records, that exists on only one of the dates (wanted)
The problem:*
Duplicate records, that have the same id, and exist in both dates and have equal production values (not wanted)
My current query, that need change
select project_id
name
CASE
WHEN max(stories_produced) - min(stories_produced) = 0
THEN max(stories_produced)
ELSE max(stories_produced) - min(stories_produced)
END AS 'stories_produced'
from project_prod
WHERE on_date IN ('2017-03-01', '2017-06-10')
group by project_id;
output example:
id name stories_produced
1042 project 1 800 (wanted)
1568 project 2 355 (wanted)
1405 project 3 1 (not wanted)
The CASE is currently not taking care of the third constraint (Duplicate records, that have the same id, and exist in both dates and have EQUAL production values (not wanted))
Is there any possible condition that can accommodate this?
One option uses not exists to drop rows that have the same id, and exist in both dates and have equal production values:
select
p.project_id,
p.name,
p.stories_produced,
p.on_date,
from project_prod p
where
on_date in ('2017-03-01', '2017-06-10')
and not exists (
select 1
from project_prod p1
where
p1.on_date in ('2017-03-01', '2017-06-10')
and p1.on_date <> p.date
and p1.id = p.id
and p1.stories_produced = p.stories_produced
)
order by project_id
In MySQL 8.0, you can use window functions:
select
project_id,
name,
stories_produced,
on_date,
from (
select
p.*,
min(stories_produced) over(partition by project_id) min_stories_produced,
max(stories_produced) over(partition by project_id) max_stories_produced,
count(*) over(partition by project_id) max_stories_produced cnt
from project_prod p
where on_date in ('2017-03-01', '2017-06-10')
) t
where not (cnt = 2 and min_stories_produced = max_stories_produced)
oder by project_id

Mysql Fetch entire row where value is max

I'm trying the following
Table : teams_members
Id Team_id User_id
1 103 65524
14 103 65529
16 103 65530
17 103 65526
19 103 65528
Table : users
Id username
65524 Kaiprioska
65526 Darkstarling
65528 Metazoans98
65529 Darth Laser
65530 TheBourbonKid
Table : users_playeraccounts
Id user_id summoner_name rank_solo
7 65524 kaiprioska 19
8 65524 swaggapandaa 14
9 65524 Yolonese Prophet 12
10 65529 Darth Laser 15
11 65530 TheBourbonkid 18
12 65528 Metazoans98 9
13 65530 TheBourbonKid 12
What the result needs to be :
user_id summoner_name rank_solo
65524 kaiprioska 19
65529 Darth laser 15
65530 TheBourbonkid 18
65528 metazoans98 9
655529 darth laser 15
So every teammember I need the users_playeraccounts entry where rank_solo is max for that user_id. I can get the full list so every playeraccount for every member but not the max entry.
Any assistance would be greatly appreciated.
select user_id, summoner_name, max(rank_solo ) as rank_solo
from users_playeraccounts
group by user_id
Try this
SELECT USER_ID, SUMMONER_NAME, MAX(RANK_SOLO) FROM users_playeraccounts GROUP BY USER_ID
You'll need to query the table twice; once to get the highest ranks, and another to retrieve the records of them. (As an aside, if the user has two at highest rank, both with be in the results.)
SELECT q.user_id, q.summoner_name, q.rank_solo
FROM (
SELECT user_id, MAX(rank_solo) AS rank_solo
FROM users_playeraccounts
GROUP BY user_id
) As maxQ
INNER JOIN users_playeraccounts AS q USING (user_id, rank_solo)
GROUP BY q.user_id -- If you only want one per user.
;
SELECT u.id, u.username, solo_rank FROM (
SELECT [user_id] userID, MAX(rank_solo) solo_rank FROM users_playeraccounts GROUP BY [user_id]
) BestSoloRanking
JOIN users u ON BestSoloRanking.userID = u.id

SQL can't figure out how to join correctly

Having a joining issue
I have one table that has an ID and description column the seasons are new, but the descriptions repeat. so we can have an Adult price for season 34 and an adult price for season 35 etc.
select * from tableA
-- returns id, description, price, season etc ...
-- 1 "GT Adult" 10 34
-- 2 "GT Child" 5 34
-- 3 "GT Senior" 8 34
-- 1 "GT Adult" 11 35
-- 2 "GT Child" 6 35
-- etc.
TableB has multiple columns these columns have names/headers that correspond to the description column.
select * from tableB
-- returns customer_no adult, child, senior, order_dt, order_data, season, perf_no etc.
-- returns 112 0, 12, 2, order_dt, order_data, order_season.
-- returns 415 23, 0, 0, order_dt, order_data, order_season.
Basically each customer places an order for a given amount of tickets of each type.
The information we can use to join is season and performance that they match on ...
but i can't figure out how to say for customer 112 since he got 12 children's tickets he should be charged 5 a ticket, and 2 senior tickets he should be charged 8 dollar for each of those tickets.
Where as customer 415 should be charged $10 for each of the 23 tickets. by season.
The only thing I can do for sure is join on season but how do i join on the correct column.
Please advise.
I don't think you can do what you want with the tables you have. There is no clear way to associate the "adult" column in TableB with the row that contains "GT Adult" in TableA.
You could redesign TableB to solve this:
TableB (customer_no, ticket_type, quantity, order_dt, ...)
So for customer 112 we would have in TableB:
112, "GT_Child", 12 ...
112, "GT_Senior", 2 ...
So you can answer your queries by joining on ticket_type (and possibly other columns if you need them).
If possible, you should move the details of the order itself into a third table (let's call it TableC) and allocate an order number. So we would now have TableA as you have it and then:
TableB (order_no, customer_no, ticket_type, quantity)
TableC (order_no, order_dt, season ...)
You can use PIVOT to get all ticket prices in a single row per season:
SELECT season, [GT Adult], [GT Child], [GT Senior]
FROM (
SELECT season, price, [description]
FROM tableA
) source
PIVOT (
MAX(price)
FOR [description] IN ([GT Adult], [GT Child], [GT Senior])
) pvt
Given the sample data quoted in the OP, the above produces sth like:
season GT Adult GT Child GT Senior
-----------------------------------------
34 10 5 8
35 11 6 NULL
Then you can perform a simple INNER JOIN operation in order to get the total amount per customer order:
SELECT customer_no, adult * [GT Adult] + child * [GT Child] + senior * [GT Senior] AS total
FROM tableB AS B
INNER JOIN (
SELECT season, [GT Adult], [GT Child], [GT Senior]
FROM (
SELECT season, price, [description]
FROM tableA) source
PIVOT (
MAX(price)
FOR [description] IN ([GT Adult], [GT Child], [GT Senior])
) pvt
) t ON b.season = t.season
SQL Fiddle Demo
P.S. The above query works in SQL Server.
EDIT:
To simulate PIVOT in MySQL we have to use conditional aggregates:
select season,
sum(if(description='GT Adult', price ,null)) as adultPrice,
sum(if(description='GT Child', price ,null)) as childPrice,
sum(if(description='GT Senior', price ,null)) as seniorPrice
from tableA
group by season;
The above query gives us the result set with which a JOIN operation can be performed:
SELECT customer_no, adult * adultPrice + child * childPrice + senior * seniorPrice AS total
FROM tableB AS b
INNER JOIN (
SELECT season,
SUM(IF(description='GT Adult', price ,null)) AS adultPrice,
SUM(IF(description='GT Child', price ,null)) AS childPrice,
SUM(IF(description='GT Senior', price ,null)) AS seniorPrice
FROM tableA
GROUP BY season) AS a ON b.season = a.season
MySQL Demo here

SUM 2 Field from 2 different tables

I have a mysql query like this :
SELECT SUM(bills.Amount) AS AmountExpense, SUM(assets.Amount) as AmountIncome
FROM bills, assets where bills.UserId = 11 and assets.UserId =11
Sample Bills table
id payee description UserId Amount
1 john advance 11 15.0
2 dave request 2 13.0
3 er request 11 12.0
Sample assets table
id payee description UserId Amount
1 john advance 11 40.2
2 dave request 2 13.0
3 ww request 11 14.00
I have a problem with AmountExpense, the record SUM record multiple time. I have successed with Amount Income. Any suggestions?
You have most likely more than one row per user on one or both of those tables. You'll need to join them after performing the aggregation. Also, please don't use old style non ANSI implicit joins:
SELECT AmountExpense, AmountIncome
FROM ( SELECT UserId,
SUM(Amount) AS AmountExpense
FROM bills
GROUP BY UserId) AS b
LEFT JOIN ( SELECT UserId,
SUM(Amount) AmountIncome
FROM assets
GROUP BY UserId) AS a
ON b.UserId = a.UserId
WHERE b.UserId = 11
If you have the possibility that users can be in either table, but not the other, then you want the equivalent of a full outer join. MySQL doesn't support that syntax, but it does support this:
select userid, sum(amountexpense) as amountexpense, sum(amountincome) as amountincome
from (select userid, amount as amountexpense, null as amountincome
from bills
union all
select userid, null, amount as amountincome
from assets
) ba
group by userid;

Select distinct ID's

We would like an SQL statement that lists the number of times a unique IP/uniqueID pair has visited on any unique date ordered by the maximum numbers of times that the UniqueID/IP pair has visited.
Here is the table structure:
Column Type
------------------------------
Date Timestamp
NumberofUsers smallint
ipaddress varchar(16)
location varchar(2)
Count bigint(20)
Here is the sql we have been trying:
SELECT
LicenseID,
MAX(Date) AS LatestAccess,
COUNT(DISTINCT Location) AS DifferentCountries,
COUNT(DISTINCT IPAddress) AS DistinctIPCount,
COUNT(DISTINCT Date,IPAddress) AS DistinctDate
FROM
LicenseHistory
WHERE
(LicenseID<>30002)
GROUP BY
LicenseID
ORDER BY
DistinctDate DESC
Here is some sample date from the table in CSV format:
2009-10-08 10:37,30002,8,24.108.64.80,CA,2399
2009-05-27 16:57,24508,50,24.108.64.80,CA,645
2008-11-06 12:04,30,100,24.108.64.80,CA,282
2008-02-04 10:51,24508,30,24.69.19.207,CA,62
2009-10-08 14:52,13136,5,24.108.64.80,CA,285
2013-05-13 13:10,718,10,66.251.68.106,US,23860
2008-02-12 11:10,30002,8,24.69.19.207,CA,36
2008-04-09 17:49,18504,10,70.90.32.57,US,121
2007-07-26 13:38,30002,8,76.226.201.191,US,2
2009-12-03 22:35,30002,8,196.25.255.214,ZA,14
2013-05-13 6:49,20341,4,66.232.201.125,US,2676
2007-07-28 23:57,30002,8,75.81.107.238,US,1
2007-07-29 10:39,30002,8,70.63.54.162,US,1
2007-07-30 3:53,30002,8,121.210.199.31,AU,4
2007-07-30 5:11,30002,8,41.207.67.10,KE,2
Here is some sample results (not correct yet, last column should not match second to last):
uniqueID LatestAccess DifferentCountries DistinctIPCount DistinctDate
--------------------------------------------------------------------------------
20677 2013-05-13 18:20:15 4 162 162
27749 2013-05-14 05:30:59 7 155 155
459 2013-05-13 11:12:47 2 143 143
24965 2013-05-14 13:44:56 6 123 123
25226 2013-05-06 16:11:56 3 104 104
20370 2013-05-14 05:54:04 4 100 100
The problem I think is in the "COUNT(DISTINCT Date,IPAddress) AS DistinctDate" piece.
You need a COUNT DISTINCT. Here's a guess because there's no table structure provided:
SELECT
VisitDate,
COUNT(DISTINCT IPAddress, UniqueID) AS UniqueVisits
FROM MyTable
GROUP BY VisitDate
ORDER BY UniqueVisits DESC
Or if your visit date is a datetime or timestamp, cut out the time part with the DATE function (note the changes on the second and fifth lines):
SELECT
DATE(VisitDate),
COUNT(DISTINCT IPAddress, UniqueID) AS UniqueVisits
FROM MyTable
GROUP BY DATE(VisitDate)
ORDER BY UniqueVisits DESC
Your date format has a time in it. So, I think all the dates are unique. Try this:
SELECT
LicenseID,
MAX(Date) AS LatestAccess,
COUNT(DISTINCT Location) AS DifferentCountries,
COUNT(DISTINCT IPAddress) AS DistinctIPCount,
COUNT(DISTINCT date(Date), IPAddress) AS DistinctDate
FROM
LicenseHistory
WHERE
(LicenseID<>30002)
GROUP BY
LicenseID
ORDER BY
DistinctDate DESC