Finding some same values within each ID - sql

I have this kind of data, with ID column identifying potential duplicates,
in this data same Id means it is a same customer, what I want to do is show that 456 account not required as it is covered under account 123, is there a way I can do that on SQL or tableau? I want to show all accounts like 456 within ID group.

with cte as (
select min(customer_account) as account, id --This query will get the first account for each ID
from table
group by ID
)
select customer_account, id --this will show, for each id, all the 'duplicated' customers
from table
where customer_account not in (select account from cte)
the result should be:
456 1
789 1
ID with just one customer ID won't appear

Write a SQL query that selects the minimum Customer value for each ID. Join that dataset back to the original table where the original table's Customer value is greater than the minimum for each corresponding ID. Here is a SQLFiddle example:
http://www.sqlfiddle.com/#!9/93296f/20
Here is the DDL used to recreate your question:
CREATE TABLE Table1
(`Id` int, `Customer_Account` int, `City` varchar(9));
INSERT INTO Table1
(`Id`, `Customer_Account`, `City`)
VALUES
(1, 123, 'London'),
(1, 123, 'Paris'),
(1, 456, 'Paris'),
(1, 456, 'Mumbai'),
(1, 123, 'Mumbai'),
(1, 789, 'Singapore');
Here is the DML used to show the duplicate Customer Accounts. Query 3 should give you the final results.
-- Query 1: Find the First Account for each Customer
select `Id`,
min(`Customer_Account`) as 'First Account by Customer'
from Table1 group by `Id`;
-- Query 2: Find the First Account for Each Customer by City
select `Id`,
min(`Customer_Account`) as 'First Account by City',
`City`
from Table1
group by `Id`, `City`;
-- Query 3: Find the Duplicate Customer Accounts by ID
select distinct
A.Id,
A.Customer_Account as 'Duplicate Account by Customer',
FirstAcctList.First_Account
from Table1 A
join (
select
`Id`,
min(`Customer_Account`) as 'First_Account'
from Table1 group by `Id`) as FirstAcctList
on FirstAcctList.First_Account <> A.Customer_Account;

Related

How to get unique records from 3 tables

I have 3 tables and I am trying to get unique results from all 3 tables (including other columns from each table).
I have tried union approach but that approach only works when I have single column selected from each table.
As soon as I want another corresponding column value from each table, I don't get unique values for the field I am trying to get.
Sample Database and query available here as well: http://www.sqlfiddle.com/#!18/1b9a6/10
Here is the example tables i have created.
CREATE TABLE TABLEA
(
id int,
city varchar(6)
);
INSERT INTO TABLEA ([id], [city])
VALUES
(1, 'A'),
(2, 'B'),
(3, 'C');
CREATE TABLE TABLEB
(
id int,
city varchar(6)
);
INSERT INTO TABLEB ([id], [city])
VALUES
(1, 'B'),
(2, 'C'),
(3, 'D');
CREATE TABLE TABLEC
(
id int,
city varchar(6)
);
INSERT INTO TABLEC ([id], [city])
VALUES
(1, 'C'),
(2, 'D'),
(2, 'E');
Desired result:
A,B,C,D,E
Unique city from all 3 table combined. By unique, I am referring to DISTINCT city from the combination of all 3 tables. Yes, the id is different for common values between tables but it doesn't matter in my use-case if id is coming from table A, B OR C, as long as I am getting DISTINCT (aka UNIQUE) city across all 3 tables.
I tried this query but no luck (city B is missing in the output):
SELECT city, id
FROM
(SELECT city, id
FROM TABLEA
WHERE city NOT IN (SELECT city FROM TABLEB
UNION
SELECT city FROM TABLEC)
UNION
SELECT city, id
FROM TABLEB
WHERE city NOT IN (SELECT city FROM TABLEA
UNION
SELECT city FROM TABLEC)
UNION
SELECT city, id
FROM TABLEC) AS mytable
try this. As this should give you distinct city with there first appear id:
select distinct min(id) over(partition by city) id, city from (
select * from TABLEA
union all
select * from TABLEB
union all
select * from TABLEC ) uni
You got the right idea, just wrap the UNION results in a subquery/temp table and then apply the DISTINCT
WITH TABLEE AS (
SELECT city, id FROM TABLEA
UNION
SELECT city, id FROM TABLEB
UNION
SELECT city, id FROM TABLEC
)
SELECT DISTINCT city
FROM TABLEE

SQL Insert Select when select retrieves multiple records

Tables:
workstation
id
name
user_id
user
id
name
My business requirement is: I want two new workstations, named "A" and "B" for each user that still don't have any workstation (don't have an entry in the workstation table).
So, it's like a for each.
For each user that I found in the select I want to do two inserts (for 'A' and 'B'), like
insert into workstation(name, user_id)
values('A', select id from user where id not in (select user_id from workstation));
This doesn't work because the 'A' is hardcoded and the select retrieves multiple id's. And even if it worked for 'A', will fail for 'B' for sure.
You can insert multiple records from select statement directly as following
insert into workstation(name, user_id)
select 'A', id from user where id not in (select user_id from workstation)
union
select 'B', id from user where id not in (select user_id from workstation);
to add them to 'A' and 'B' in same time union both select in same statement to ensure you add them for 'A' and 'B' workstation
for more details you can check insert in postgre documentation
Hopefully this is more accurate for you.
insert into workstation(name, user_id)
select 'A', id from user where (select count(*) from workstation where name = 'A' and user_id = user.id) = 0
union
select 'B', id from user where (select count(*) from workstation where name = 'B' and user_id = user.id) = 0
select id from user where id not in (select user_id from workstation) may return multiple records and i guess this is where it fails. Have you tried limiting the extracted records to only single records?
Syntax might not be correct:
insert into workstation(name, user_id) values('A', (select id from user where id not in (select user_id from workstation) Limit 1))
This will get only one record that is not already present in the Workstation table even if there are multiple records for which are not already there in the workstation table.
insert into workstation ( name, user_id)
with ws as (select 'A' name from dual
union all
select 'B" from dual
)
select ws.name, user_id
from ws, users u
where not exists
(select null
from workstation w
where w.user_id = u.user_id
) ;
Note: user is a reserved word and should not be used as a table name.

select add sum below each group using select query

Sample Table :
INSERT INTO Table1
([ID], [Name])
VALUES
('1', 'Alpha'),
('2', 'Beta'),
('3', 'Beta'),
('4', 'Beta'),
('5', 'Charlie'),
('6', 'Charlie')
Using a select query, I want to add a row with the sum of id per name below every group. I've tried using union but I would need to do a select query per name. Names could change anytime though.
Select query result :
ID Name
1 Alpha
1
2 Beta
3 Beta
4 Beta
9
5 Charlie
6 Charlie
11
You can achieve this with a union having a computed column to keep track of the source name on each side of the union:
SELECT ID, Name
FROM
(
SELECT ID, Name AS position, Name FROM Table1
UNION ALL
SELECT SUM(ID), Name, NULL
FROM Table1
GROUP BY Name
) t
ORDER BY
position, ID;
Demo
SELECT SUM(Id), Name from Table1 GROUP BY name
Try this to get addition of Id field and group by Name.

Oracle SQL - IN Clause display all record given in IN condition even when data not present in table

I have a table customer as described below.
customer_id number
customer_name varchar(30)
city varchar(20)
columns. When the below query run in Oracle db
SELECT customer_id, city FROM customer WHERE city IN ('abc', 'def', 'ghi')
I'm getting the output as shown below. Table doesn't have record for ghi
customer_id, city
1, abc
2, def
I'm trying to form the output something as below.
customer_id, city
1, abc
2, def
null, ghi
Though no record for ghi in table, want to display it in SELECT query output with rest of the column value as null.
Much appreciate help in writing sql for this scenario.
You need a derived table containing all possibilities. Either you have one, like a city table and then you can do:
SELECT t.customer_id,s.city
FROM city_table s
LEFT JOIN customer t
ON(s.id = t.city)
WHERE s.city IN ('abc', 'def', 'ghi')
Or generate the values your self:
SELECT t.customer_id,s.city
FROM (SELECT 'abc' as id FROM DUAL
UNION ALL
SELECT 'def' FROM DUAL
UNION ALL
SELECT 'ghi' FROM DUAL) s
LEFT JOIN customer t
ON(s.id = t.city)
WHERE s.id IN('abc', 'def', 'ghi')

SQL query for the latest record for each day

I've got an Oracle 10g database with a table with a structure and content very similar to the following:
CREATE TABLE MyTable
(
id INTEGER PRIMARY KEY,
otherData VARCHAR2(100),
submitted DATE
);
INSERT INTO MyTable VALUES (1, 'a', TO_DATE('28/04/2010 05:13', ''DD/MM/YYYY HH24:MI));
INSERT INTO MyTable VALUES (2, 'b', TO_DATE('28/04/2010 03:48', ''DD/MM/YYYY HH24:MI));
INSERT INTO MyTable VALUES (3, 'c', TO_DATE('29/04/2010 05:13', ''DD/MM/YYYY HH24:MI));
INSERT INTO MyTable VALUES (4, 'd', TO_DATE('29/04/2010 17:16', ''DD/MM/YYYY HH24:MI));
INSERT INTO MyTable VALUES (5, 'e', TO_DATE('29/04/2010 08:49', ''DD/MM/YYYY HH24:MI));
What I need to do is query the database for the latest record submitted on each given day. For example, with the above data I would expect the records with ID numbers 1 and 4 to be returned, as these are the latest each for 28 April and 29 April respectively.
Unfortunately, I have little expertise as far as SQL is concerned. Could anybody possibly provide some insight as to how to achieve this?
Thanks in advance!
I would use a common table expression (aka CTE) like so:
With RankedItems As
(
Select Id, otherdata, submitted
, ROW_NUMBER() OVER( PARTITION BY TO_CHAR(submitted, 'YYYY-MM-DD') ORDER BY submitted DESC ) ItemRank
From MyTable
)
Select
From RankedItems
Where ItemRank = 1
I think it's as simple as:
SELECT * from MyTable ORDER BY submitted DESC LIMIT 1
Though it might be worth exploring whether there are some column/where parameters that could make the query run more quickly, particularly if you've got a query plan analyzer handy.