I am using SQL Server 2012, and have the following query. Let's call this query A.
SELECT a.col, a.fk
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col
I want to delete only the rows returned from query A, specifically rows that match the returned col AND fk
I am thinking of doing the following, but it will only delete rows that match on the col.
delete from Table1
where col in (
SELECT a.col
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col)
)
Use delete from Join syntax
delete t1
from table1 t1
INNER JOIN (SELECT a.col, a.fk
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col) t2
ON t1.col1=t2.col1 and t1.fk=t2.fk
you can combine col and fk fields to be another unique filed to retrieve wanted rows
delete from Table1
where cast(col as varchar(50))+'//'+cast(fk as varchar(50)) in (
SELECT cast(a.col as varchar(50))+'//'+cast(a.fk as varchar(50))
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col)
)
You can express Query A like this:
SELECT col, fk
FROM (
SELECT a.col, a.fk, COUNT(*) OVER (PARTITION BY a.col) AS [count]
FROM Table1 a
) counted
WHERE [count] > 1
Which leads to a nice way to do the DELETE using a CTE:
;WITH ToDelete AS (
SELECT a.col, a.fk, COUNT(*) OVER (PARTITION BY a.col) AS [count]
FROM Table1 a
)
DELETE FROM ToDelete
WHERE [count] > 1
This does give the same result as the DELETE statement in your question though.
If you want to delete all but one row with the duplicate col value you can use something like this:
;WITH ToDelete AS (
SELECT a.col, a.fk
, ROW_NUMBER() OVER (PARTITION BY a.col ORDER BY a.fk) AS [occurance]
FROM Table1 a
)
DELETE FROM ToDelete
WHERE [occurance] > 1
The ORDER BY clause will determine which row is kept.
Related
So I know MS-Access does not allow SELECT COUNT(DISTINCT....) FROM ..., but I am trying to find a more viable alternative to the usual standard of
SELECT COUNT(*) FROM (SELECT DISTINCT Name FROM table1)
My problem is I am trying to do three separate Count functions and group them on ID. If I use the method above, it is giving me the total unique value count for the whole table instead of the total count for only the value of ID. I tried doing
(SELECT COUNT(*) FROM (SELECT DISTINCT Name FROM table1 as T2
WHERE T2.ColumnA = T1.ColumnA)) As MyVal
FROM table1 as T1
but it tells me I need to specify a value for T1.ColumnA.
The SQL query I am trying to accomplish is this:
SELECT ID
COUNT(DISTINCT ColumnA) as CA,
COUNT(DISTINCT ColumnB) as CB,
COUNT(DISTINCT ColumnC) as CC
FROM table1
GROUP BY ID
Any ideas?
You can use subqueries. Assuming you have a table where each id occurs once:
select (select count(*)
from (select columnA
from table1 t1
where t1.id = t.id
group by columnA
) as a
) as num_a,
(select count(*)
from (select columnB
from table1 t1
where t1.id = t.id
group by columnB
) as b
) as num_b,
(select count(*)
from (select columnC
from table1 t1
where t1.id = t.id
group by columnC
) as c
) as num_c
from <table with ids> as t;
I'm not sure if you'll think this is "viable".
EDIT:
This makes it even more complicated . . . it suggests that MS Access doesn't support correlation clauses more than one level deep (might you consider switching to another database?).
In any case, the brute force way:
select a.id, a.numA, b.numB, c.numC
from ((select id, count(*) as numA
from (select id, columnA
from table1 t1
group by id, columnA
) as a
) as a inner join
(select id, count(*) as numB
from (select id, columnB
from table1 t1
group by id, columnB
) as b
) as b
on a.id = b.id
) inner join
(select id, count(*) as numC
from (select id, columnC
from table1 t1
group by id, columnC
) as c
) c
on c.id = a.id;
Maybe I'm searching using the wrong words because I can't find the answer elswhere, but I need to join two tables but make sure the ID from one of the tables is distinct. Something like the below:
SELECT B.COLUMN_A, B.COLUMN_B, B.COLUMN_C
FROM TABLE1 A
JOIN TABLE2 B
ON (Distinct) A.COLUMN_A = B.COLUMN_A;
The value A.COLUMN_A from TABLE1 needs to be DISTINCT.
I've tried the below but that didn't work:
SELECT B.COLUMN_A, B.COLUMN_B, B.COLUMN_C
FROM TABLE1 A
JOIN (SELECT DISTINCT COLUMN_A FROM TABLE2) B
ON A.COLUMN_A = B.COLUMN_A;
I keep getting a ORA-00904: invalid identifer error on B.COLUMN_C. If I try to use ) AS B then I get a ORA-00905: missing keyword error.
If you don't care about the other values, use group by
SELECT b.column_a, b.column_b, b.column_c
FROM table1 a
JOIN (
SELECT column_a, max(column_b) as column_b, max(column_c) as column_c
FROM table2
GROUP BY column_a
) b ON a.column_a = b.column_a
Use a ROW_NUMBER to get a single row per COLUMN_A:
SELECT *
FROM table1 A
JOIN
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY COLUMN_A ORDER BY COLUMN_A) AS rn
FROM table2
) B
ON A.column_a = B.column_a
AND B.rn = 1
Maybe you need something like this:
select * from
(
select column_a,column_b,column_c
from
(
select column_a,column_b,column_c, count(1) over (partition by column_a) as num
from tableB
)
where num = 1
)tB
inner join tableA
using (column_a)
The double nesting is not necessary, but I hope it makes the query more readable
If you need col_a, col_b, col_c and want to ensure col_a never repeats and col_b, col_c values are not germane, then :
SELECT col_a, col_b, col_c
FROM table2
WHERE rowid in ( SELECT min(rowid)
FROM table2 A , table1 B )
WHERE B.col_a = A.col_a
GROUP BY A.col_a )
In above you choose one distinct row of Table2 that is also present in Table1. Then using that row's id you select all three columns.
You are not selecting any of the columns from TABLE1, so your join to (distinct) TABLE1 records is really just a semi-join, which is most easily expressed as:
SELECT B.COLUMN_A, B.COLUMN_B, B.COLUMN_C
FROM TABLE2 B
WHERE EXISTS ( SELECT 'at least one row in table1'
FROM TABLE1 A
WHERE A.COLUMN_A = B.COLUMN_A );
I have a table like below.
Id amount
--------------
10. 12345
10. 12345
12. 34567
13. 34567
As per my business requirement same id with same amount is not duplicate record. different Ids wtih same amount is duplicate record. hope you understood the requirement.
In the above sample record I have to get the duplicate amount values and its count and at the same time Id should be different.
The expected query result is 34567 and count as 2.
IF you need to display id as well,
SELECT a.*
FROM
(
SELECT id, amount, count(1) OVER (PARTITION BY amount) num_dup
FROM table1
)a
WHERE a.num_dup >1
Update. If you care only about distinct id , use COUNT(DISTINCT id) instead of COUNT(1)
More examples.
With joining another table
SELECT a.*
FROM
(
SELECT a.id, a.amount,
count(distinct a.id) OVER (PARTITION BY a.amount) num_dup
FROM table1 a
INNER JOIN table2 b ON (b.id = a.id)
)a
WHERE a.num_dup >1
Without window function and without table1.id :
SELECT a.amount, count(distinct a.id)
FROM table1 a
INNER JOIN table2 b ON (b.id = a.id)
GROUP BY a.amount
HAVING count(distinct a.id) >1 ;
Without window function and with table1.id :
SELECT b.*
FROM
(
SELECT a.amount, count(distinct a.id)
FROM table1 a
INNER JOIN table2 b ON (b.id = a.id)
GROUP BY a.amount
HAVING count(distinct a.id) >1
)a
INNER JOIN table1 b ON (b.amount = a.amount)
I need to compare two tables on SQL server.
table1
id value
3 5
table2
id value
8 6
SELECT *
FROM
(
SELECT a.id AS a_id, a.value AS a_value
FROM [table1] as a
UNION ALL
SELECT b.id AS b_id, b.value AS b_value
FROM [table2] as b
) tmp
GROUP BY tmp.a_id, tmp.a_value
HAVING COUNT(*) = 1
ORDER BY tmp.a_id
I get result:
a_id a_value
3 5
8 6
I need to know which column is from which table, e.g.
a_id a_value b_id b_value
3 5 8 6
Any help would be appreciated !
Thanks !
What about:
SELECT *
FROM (
SELECT a.id, a.value, 'Table1' AS TableName
FROM [table1] as a
UNION ALL
SELECT b.id, b.value, 'Table2' AS TableName
FROM [table2] as b
) tmp
GROUP BY tmp.id, tmp.value, tmp.TableName
HAVING COUNT(*) = 1
ORDER BY tmp.id
You could add a column for tbl. Something like:
SELECT
m.id
,m.value
INTO #tmp
FROM
(
SELECT a.id AS id, a.value AS value
FROM [table1] as a
UNION ALL
SELECT b.id AS id, b.value AS value
FROM [table2] as b
) m
GROUP BY
m.id
,m.value
HAVING COUNT(*) = 1
CREATE CLUSTERED INDEX ix_tmpidvalue ON #tmp
(
id ASC
,value ASC
)
SELECT *
FROM
(
SELECT a.id AS id, a.value AS value, 'a' tbl
FROM [table1] as a
UNION ALL
SELECT b.id AS id, b.value AS value, 'b' tbl
FROM [table2] as b
) tmp
WHERE EXISTS
(
SELECT 1
FROM #tmp n
WHERE tmp.id = n.id
AND tmp.value = n.value
)
ORDER BY tmp.id
How can I select like this? Can I create a User defined Aggregate Function
SELECT Max(A),(SELECT TOP 1 FROM TheGroup Where B=Max(A)) FROM MyTable
where MyTable as Shown Below
A B C
--------------
1 2 S
3 4 S
4 5 T
6 7 T
I want a Query Like this
SELECT MAX(A),(B Where A=Max(A)),C FROM MYTable GROUP BY C
I'm Expecting the result as below
MAX(A) Condition C
-----------------------
3 4 S
6 7 T
SELECT A,B,C FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY C ORDER BY A DESC) RN FROM MyTable)
WHERE RN = 1
(this query will always return only one row per C value)
OR
WITH CTE_Group AS
(
SELECT C, MAX(A) AS MaxA
FROM MyTable
GROUP BY C
)
SELECT g.MaxA, t.B, g.C
FROM MyTable t
INNER JOIN CTE_Group g ON t.A = g.MaxA AND t.C = g.C
(if there are multiple rows that have same Max(A) value - this query will return all of them)
Try Following Query :
SELECT TABLE1.A , TABLE2.B , TABLE1.C
FROM
(
SELECT MAX(A) AS A,C
FROM MYTable
GROUP BY C
) AS TABLE1
INNER JOIN
(
SELECT *
FROM MYTable
) AS TABLE2 ON TABLE1.A = TABLE2.A
SQLFIDDLE
you can do it by simple join query . join query always run faster then In query . Join query run only one time at the time of execution of the query . we can archive same result by using IN query .
SELECT t1.*
FROM YourTable t1
Left Outer Join YourTable t2 on t1.C=t2.C AND t1.A < t2.A
WHERE t2.A is null
how about this:
SELECT *
FROM MyTable
WHERE A IN (SELECT MAX(A) FROM MyTable GROUP BY C)
SELECT Max(A)
FROM MyTable
Where B=(SELECT Max(A) FROM MyTable)
update:
SELECT *
FROM MyTable
Where B=(SELECT Max(A) FROM MyTable)
update 2:
SELECT DISTINCT A, B
FROM MyTable
Where A=(SELECT Max(A) FROM MyTable GROUP BY C)
update 3:
ok, I think I understand what you're looking for now.. How about this:
SELECT *
FROM MyTable
Where A in (SELECT Max(A) FROM MyTable GROUP BY C)
WITH
cte AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY cola desc) AS Rno,
*
FROM
tbl
)
SELECT top 1
cola,colb
FROM
cte
order by Rno
Then try it:
WITH
cte AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY col3 ORDER BY col1 desc) AS Rno,
*
FROM
tbl
)
SELECT
col1,col2,col3
FROM
cte
WHERE Rno=1