I have a requirement to update a column in table A if the count of records in table B grouped by 3 columns (matching between A and B) is less than 7. I have written below query, but it is running long. Please suggest any optimal query or tune this.
update /*+ parallel(A) */ A set A.col4=0
where exists
(select 1
from B
where A.col1=B.col1 and A.col2=B.col2
and A.col3=B.col3
group by col1,col2,col3
having count(*) < 7)
Try this,
MERGE INTO A
USING (
SELECT col1, col2, col3
FROM B
GROUP BY col1, col2, col3
HAVING COUNT(*) > 7
) b ON (A.col1 = b.col1 AND A.col2=b.col2 AND A.col3= b.col3)
WHEN MATCHED THEN UPDATE
SET A.col4 = 0;
View it on SQL Fiddle: http://www.sqlfiddle.com/#!4/dcdf1/17
Let me know if it worked or not!
My first suggestion is to create an index on B: B(col1, col2, col3).
The next attempt would be to switch this to a join:
update A
set col4 = 0
from (select col1, col2, col3
from B
group by col1, col2, col3
having count(*) < 7
) B
where A.col1 = B.col1 and A.col2 = B.col2
and A.col3 = B.col3 ;
Related
I have been working on trying to convert the following SQL-Server code to achieve a similar result in MS Access.
WITH TableA(Col1, Col2, Col3)
AS (SELECT 'Dog',1,1 UNION ALL
SELECT 'Cat',27,86 UNION ALL
SELECT 'Cat',128,92),
TableB(Col1, Col2, Col3)
AS (SELECT 'Dog',1,1 UNION ALL
SELECT 'Cat',27,105 UNION ALL
SELECT 'Lizard',83,NULL)
SELECT CA.*
FROM TableA A
FULL OUTER JOIN TableB B
ON A.Col1 = B.Col1
AND A.Col2 = B.Col2
/*Unpivot the joined rows*/
CROSS APPLY (SELECT 'TableA' AS what, A.* UNION ALL
SELECT 'TableB' AS what, B.*) AS CA
/*Exclude identical rows*/
WHERE EXISTS (SELECT A.*
EXCEPT
SELECT B.*)
/*Discard NULL extended row*/
AND CA.Col1 IS NOT NULL
ORDER BY CA.Col1, CA.Col2
Gives
what Col1 Col2 Col3
------ ------ ----------- -----------
TableA Cat 27 86
TableB Cat 27 105
TableA Cat 128 92
TableB Lizard 83 NULL
So far I have been able to convert get replication of the FULL OUTER JOIN using the following code, but I have been unable to replicate unpivoting the joint rows (CROSS APPLY).
(SELECT *
FROM TableA AA
INNER JOIN TableB BB ON AA.Col1 = BB.Col1
UNION ALL
SELECT *
FROM TableA AA
LEFT JOIN TableB BB ON AA.Col1 = BB.Col1
WHERE BB.[IP Number] IS NULL
UNION ALL
SELECT *
FROM TableA AA
RIGHT JOIN TableB BB ON AA.Col1 = BB.Col1
WHERE AA.Col1 IS NULL
)
I could use some help achieving the same result in a MS-Access query.
From what I can gather, you have two tables that have unique rows. You want to return rows that are present in one table but not the other.
I would suggest aggregation and HAVING for this -- in either database:
SELECT col1, col2, col3
FROM ((SELECT col1, col2, col3 FROM TableA) UNION ALL
(SELECT col1, col2, col3 FROM TableB)
) as ab
GROUP BY col1, col2, col3
HAVING COUNT(*) = 1;
Or alternatively, two NOT EXISTS clauses:
SELECT a.*
FROM TableA as a
WHERE NOT EXISTS (SELECT 1
FROM TableB as b
WHERE (a.col1 = b.col1 OR a.col1 IS NULL AND b.col1 IS NULL) AND
(a.col2 = b.col2 OR a.col2 IS NULL AND b.col2 IS NULL) AND
(a.col3 = b.col3 OR a.col3 IS NULL AND b.col3 IS NULL)
)
UNION ALL
SELECT b.*
FROM TableB as b
WHERE NOT EXISTS (SELECT 1
FROM TableA as a
WHERE (a.col1 = b.col1 OR a.col1 IS NULL AND b.col1 IS NULL) AND
(a.col2 = b.col2 OR a.col2 IS NULL AND b.col2 IS NULL) AND
(a.col3 = b.col3 OR a.col3 IS NULL AND b.col3 IS NULL)
);
Here is a db<>fiddle that uses SQL Server, but the syntax should be basically the same in MS Access.
I have following table in Postgres 11:
col1 col2 col3 col4
1 trial_1 ag-270 ag
2 trial_2 ag ag
3 trial_3 methotexate (mtx) mtx
4 trial_4 mtx mtx
5 trial_5 hep-nor-b nor-b
I would like to search each value of col4 throughout the column col3. If the value in col4 exists in col3, I would like to keep the rows else the row should be excluded.
Desired output is:
col1 col2 col3 col4
1 trial_1 ag-270 ag
2 trial_2 ag ag
3 trial_3 methotexate (mtx) mtx
4 trial_4 mtx mtx
I could not try anything on this as I am unable to find a solution to this yet.
If the value in col4 exists in col3, I would like to keep the rows.
... translates to:
SELECT *
FROM tbl a
WHERE EXISTS (SELECT FROM tbl b WHERE b.col3 = a.col4);
db<>fiddle here
Produces your desired result.
This can be done as an inner join:
select distinct t.col1, t.col2, t.col3, t,col4
from T t inner join T t2 on t2.col3 = t.col4
select a.*
from myTable a
where exists (
select 1
from myTable b
where b.col3 = a.col4)
If your table has many rows, you should ensure that col3 is indexed.
So I am currently trying to take one table and add it into another table but for some reason it is not working the way I want it to.
There are three columns in both the tables and I only want to add each row of data from table 2 to table 1 if the first 2 columns of table 2 are not already in table 1 (I dont care about the 3rd column)
This is what I have so far:
INSERT INTO table1 (col1, col2, col3)
SELECT a.col1, a.col2, a.col3
FROM table2 as a
WHERE NOT EXISTS (SELECT b.col1, b.col2
FROM table1 as b
WHERE a.col1 = b.col1 AND a.col2 = b.col2);
I checked around and this seems that it should work but it isn't but can anyone see why?
I often have trouble when there are two fields to search for. One way is to combine them together:
INSERT INTO table1 (col1, col2, col3)
SELECT a.col1, a.col2, a.col3 from table2 as a
WHERE concat(a.col1,':', a.col2)
NOT IN (SELECT concat(col1,':',col2) from table1);
Another way is a left join:
INSERT INTO table1 (col1, col2, col3)
SELECT a.col1, a.col2, a.col3
from table2 as a
LEFT OUTER JOIN table1 as b
ON a.col1 = b.col1
AND a.col2 = b.col2
WHERE b.col1 IS NULL AND b.col2 IS NULL;
For example 2, it is better to use a primary key in the where clause.
Try this:
merge into tab2 a
using
(select col1,col2,col3 from tabl1) b
on
(b.col1=a.col1 and b.col2=a.col2)
when not matched then
insert (a.col1,a.col2,a.col3)
values
(b.col1,b.col2,b.col3);
Try this:
INSERT INTO table1 (col1, col2, col3)
(SELECT a.col1, a.col2, a.col3
FROM table2 a
WHERE NOT EXISTS (SELECT b.col1, b.col2
FROM table1 b
WHERE a.col1 = b.col1 AND a.col2 = b.col2));
I guess for table name as is not needed.
I would like to
Select columns from table a
Where extension table a = extension in table b
And department in both table b and table c match
Based on that match that deptartment in table c should = yes
Select col1, col2, col3, col4, col5 from table a
Where col2 table a = col2 table b
And col3 in table b = col3 in table c
And col4 tabel c = yes
can anyone help.
Although your question is ambiguous have you tried:
SELECT A.COL1, A.COL2, A.COL3, A.COL4, A.COL5
FROM TABLE_A A
JOIN TABLE_B B
ON A.Extension = B.Extension
JOIN TABLE_C C
ON B.Department = C.Department
AND C.Department = 'yes'
You can do this in different ways. As following:
Way 1
SELECT col1, col2, col3, col4, col5
FROM tableA
JOIN tableB ON tableA.col2 = tableB.col2
JOIN tableC ON tableB.col3 = tableC.col3 AND tableC.col4 = 'yes'
Way 2
SELECT col1, col2, col3, col4, col5
FROM tableA
JOIN tableB ON tableA.col2 = tableB.col2
JOIN tableC ON tableB.col3 = tableC.col3
WHERE tableC.col4 = 'yes'
Way 3
SELECT *
INTO #col4yesTable
FROM tableC
Where col4 = 'yes'
SELECT tableA.col1, tableA.col2, tableA.col3, tableA.col4, tableA.col5
FROM #col4yesTable
JOIN tableB ON #col4yesTable.col3 = tableB.col3
JOIN tableB ON tableA.col2 = tableB.col2
Depends on your need you can use one of them. The last one, creates a temporary table to store all tableC objects that has col4 = 'yes'
I have a table that has redundant data and I'm trying to identify all rows that have duplicate sub-rows (for lack of a better word). By sub-rows I mean considering COL1 and COL2 only.
So let's say I have something like this:
COL1 COL2 COL3
---------------------
aa 111 blah_x
aa 111 blah_j
aa 112 blah_m
ab 111 blah_s
bb 112 blah_d
bb 112 blah_d
cc 112 blah_w
cc 113 blah_p
I need a SQL query that returns this:
COL1 COL2 COL3
---------------------
aa 111 blah_x
aa 111 blah_j
bb 112 blah_d
bb 112 blah_d
Does this work for you?
select t.* from table t
left join ( select col1, col2, count(*) as count from table group by col1, col2 ) c on t.col1=c.col1 and t.col2=c.col2
where c.count > 1
With the data you have listed, your query is not possible. The data on rows 5 & 6 is not distinct within itself.
Assuming that your table is named 'quux', if you start with something like this:
SELECT a.COL1, a.COL2, a.COL3
FROM quux a, quux b
WHERE a.COL1 = b.COL1 AND a.COL2 = b.COL2 AND a.COL3 <> b.COL3
ORDER BY a.COL1, a.COL2
You'll end up with this answer:
COL1 COL2 COL3
---------------------
aa 111 blah_x
aa 111 blah_j
That's because rows 5 & 6 have the same values for COL3. Any query that returns both rows 5 & 6 will also return duplicates of ALL of the rows in this dataset.
On the other hand, if you have a primary key (ID), then you can use this query instead:
SELECT a.COL1, a.COL2, a.COL3
FROM quux a, quux b
WHERE a.COL1 = b.COL1 AND a.COL2 = b.COL2 AND a.ID <> b.ID
ORDER BY a.COL1, a.COL2
[Edited to simplify the WHERE clause]
And you'll get the results you want:
COL1 COL2 COL3
---------------------
aa 111 blah_x
aa 111 blah_j
bb 112 blah_d
bb 112 blah_d
I just tested this on SQL Server 2000, but you should see the same results on any modern SQL database.
blorgbeard proved me wrong -- good for him!
Join on yourself like this:
SELECT a.col3, b.col3, a.col1, a.col2
FROM tablename a, tablename b
WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.col3 != b.col3
If you're using postgresql, you can use the oid to make it return less duplicated results, like this:
SELECT a.col3, b.col3, a.col1, a.col2
FROM tablename a, tablename b
WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND a.col3 != b.col3
AND a.oid < b.oid
Don't have a database handy to test this, but I think it should work...
select
*
from
theTable
where
col1 in
(
select
col1
from
theTable
group by
col1||col2
having
count(col1||col2) > 1
)
My naive attempt would be
select a.*, b.* from table a, table b where a.col1 = b.col1 and a.col2 = b.col2 and a.col3 != b.col3;
but that would return all the rows twice. I'm not sure how you'd restrict it to just returning them once. Maybe if there was a primary key, you could add "and a.pkey < b.pkey".
Like I said, that's not elegant and there is probably a better way to to do this.
Something like this should work:
SELECT a.COL1, a.COL2, a.COL3
FROM YourTable a
JOIN YourTable b ON b.COL1 = a.COL1 AND b.COL2 = a.COL2 AND b.COL3 <> a.COL3
In general, the JOIN clause should include every column that you're considering to be part of a "duplicate" (COL1 and COL2 in this case), and at least one column (or as many as it takes) to eliminate a row joining to itself (COL3, in this case).
This is pretty similar to the self-join, except it will not have the duplicates.
select COL1,COL2,COL3
from theTable a
where exists (select 'x'
from theTable b
where a.col1=b.col1
and a.col2=b.col2
and a.col3<>b.col3)
order by col1,col2,col3
Here is how you find duplicates. Tested in oracle 10g with your data.
select * from tst
where (col1, col2) in
(select col1, col2 from tst group by col1, col2 having count(*) > 1)
select COL1,COL2,COL3
from table
group by COL1,COL2,COL3
having count(*)>1
Forget joins -- use an analytic function:
select col1, col2, col3
from
(
select col1, col2, col3, count(*) over (partition by col1, col2) rows_per_col1_col2
from table
)
where rows_per_col1_col2 > 1