SQL Check column present more than once - sql

Consider a table A. Table A has a column named INNETTEDTXNID which is not the Primary key and neither unique and can be null.
I have a select * on table A based on some condition(not related to column INNETTEDTXNID).
For each of the rows fetched above i have to find a value called isNetted. The concept of isNetted is that if the column INNETTEDTXNID of this row is present more than once in the entire table(including this row) then the value of isNetted would be true for this row.
I hope my question is clear. Thanks for advance in help.

This will return the values of any entries that appear more than once.
SELECT a.INNETTEDTXNID
FROM TableA as a, TableA as b
WHERE
not a.id=b.id
and a.INNETTEDTXNID=b.INNETTEDTXNID
if your trying to do this specifically to check if a single number appears more than once you could do something like
SELECT COUNT(INNETTEDTXNID)
FROM TableA
WHERE INNETTEDTXNID='value'
if it returns one, then its unique, for more than one its not unique. IF you want it to return something like true or false you could use
SELECT
CASE WHEN (
SELECT COUNT(INNETTEDTXNID)
FROM TableA
WHERE INNETTEDTXNID='value'
)>1 THEN 'True'
ELSE 'False'
END
AS isNetted

Probably no-where near the most efficient but it works.
SELECT TableA.INNETTEDTXNID,
CASE
WHEN NetChk.INNETTEDTXNID IS NOT NULL Then 1
ELSE 0
END AS isNetted
FROM TABLEA
LEFT JOIN (
SELECT INNETTEDTXNID
FROM TableA
GROUP BY INNETTEDTXNID
HAVING COUNT(INNETTEDTXNID) >1)
NetChk ON TableA.INNETTEDTXNID = NetChk.INNETTEDTXNID

Related

Store only 1 values and remove the rest for same duplicated values in bigquery

I have duplicated values in my data. However, from the duplicated values, i only want to store 1 values and remove the rest of same duplicated values.
So far, I have found the solution where they remove ALL the duplicated values like this.
Code:
SELECT ID, a.date as date.A, b.date as date.B,
CASE WHEN a.date <> b.date THEN NULL END AS b.date
except(date.A)
FROM
table1 a LEFT JOIN table2 b
USING (ID)
WHERE date.A = 1
Sample input:
Sample output (Store only 1 values from the duplicated values and remove the rest):
NOTE: query might wrong as it remove all duplicated values.
Considering your screenshot's sample data and your explanation. I understand that you want to remove duplicates from your table retaining only one row of unique data. Thus, I was able to create a query to select only one row of data ignoring the duplicates.
In order to select the rows without any duplicates, you can use SELECT DISTINCT. According to the documentation, it discards any duplicate rows. In addition to this method, CREATE TABLE statement will also be used to create a new table (or replace the previous one) with the new data without duplicates. The syntax is as follows:
CREATE OR REPLACE TABLE project_id.dataset.table AS
SELECT DISTINCT ID, a.date as date.A, b.date as date.B,
CASE WHEN a.date <> b.date THEN NULL END AS b.date
except(date.A)
FROM
table1 a LEFT JOIN table2 b
USING (ID)
WHERE date.A = 1
And the output will be exactly the same as you shared in your question.
Notice that I used CREATE OR REPLACE, which means if you set project_id.dataset.table to the same path as the table within your select, it will replace your current table (in case you have the data coming from one unique table). Otherwise, it will create a new table with the specified new table's name.
You can use aggregation. Something like this:
SELECT ANY_VALUE(a).*, ANY_VALUE(b).*
FROM table1 a LEFT JOIN
table2 b
USING (ID)
WHERE date.A = 1
GROUP BY id, a.date;
For each id/datecombination, this returns an arbitrary matching row froma/b`.

how to have a Link from main query to sub query

I am inserting two values from one table to another table. One of the inserted values comes from concatenating three column values.
I am using the below query, but the error says "subquery has more than one value."
We can't include "top 1" into sub query which gives same value to all.
insert into dbo.tblCrucibleLdgDtls (R2IGTNo,TotalMtrlWgt)
Select R2IGTNo,
(select RTRIM(LTRIM(( CONCAT(ULTotalS1S2MtrlWgt,ULTotalS3S4MtrlWgt,ULTotalS5S6MtrlWgt)))) as TotalMtrlWgt
from dbo.tbl1RMWeighingDetails
where ULTotalS1S2MtrlWgt is not null or ULTotalS3S4MtrlWgt is not null or ULTotalS5S6MtrlWgt is not null
)
from dbo.tbl1RMWeighingDetails
where R2IGTNo like '%C%'
From Table
Solution may be simple. I am not a expert.There is no duplicates and (ULTotalS1S2MtrlWgt,ULTotalS3S4MtrlWgt,ULTotalS5S6MtrlWgt) has unique relation with R2IGTNo. Like if R2IGTNo has b1 then ULTotalS1S2MtrlWgt has value, if R2IGTNo has b2 then ULTotalS3S4MtrlWgt has value, if R2IGTNo has b3 then ULTotalS5S6MtrlWgt has value. with that condition query can be altered.
pls suggest.
Give alias names to the tables:
SELECT ..., (SELECT ... FROM dbo.tbl1RMWeighingDetails wdA)
FROM dbo.tbl1RMWeighingDetails wdB
...
Now the inner/nested sub query can reference wdB, and it will mean the outer instance of the table.
But also, this has the look of something that would be better done with a JOIN, APPLY, or windowing function.
The solution depends on what type of rows you are getting from the inner query. If your inner query returns multiple duplicate rows then the solution is simpler, just use a distinct -
insert into dbo.tblCrucibleLdgDtls (R2IGTNo,TotalMtrlWgt)
Select R2IGTNo,
(select distinct RTRIM(LTRIM((CONCAT(ULTotalS1S2MtrlWgt,ULTotalS3S4MtrlWgt,ULTotalS5S6MtrlWgt)))) as TotalMtrlWgt
from dbo.tbl1RMWeighingDetails
where ULTotalS1S2MtrlWgt is not null or ULTotalS3S4MtrlWgt is not null or ULTotalS5S6MtrlWgt is not null
)
from dbo.tbl1RMWeighingDetails
where R2IGTNo like '%C%'
But if your inner query returns multiple rows which are different from one another then you have to revisit your requirement.
I got the answer by using cte, suggestion got in MS forum
insert into dbo.tblCrucibleLdgDtls (R2IGTNo,TotalMtrlWgt)
Select R2IGTNo, coalesce(ULTotalS1S2MtrlWgt,ULTotalS3S4MtrlWgt,ULTotalS5S6MtrlWgt) as TotalMtrlWgt from dbo.tbl1RMWeighingDetails where R2IGTNo like '%C%'
or
with cte1 as(
select R2IGTNo,RTRIM(LTRIM(( CONCAT(ULTotalS1S2MtrlWgt,ULTotalS3S4MtrlWgt,ULTotalS5S6MtrlWgt)))) as TotalMtrlWgt
from dbo.tbl1RMWeighingDetails
where R2IGTNo like '%C%'
and (ULTotalS1S2MtrlWgt is not null
or ULTotalS3S4MtrlWgt is not null
or ULTotalS5S6MtrlWgt is not null))
insert into dbo.tblCrucibleLdgDtls (R2IGTNo,TotalMtrlWgt)
select * from cte1
Anyway Thank you all. -shankar

Oracle SQL Update one table column with the value of another table

I have a table A, where there is a column D_DATE with value in the form YYYYMMDD (I am not bothered about the date format). I also happen to have another table B, where there is a column name V_TILL. Now, I want to update the V_TILL column value of table B with the value of D_DATE column in table A which happens to have duplicates as well. Meaning, the inner query can return multiple records from where I form a query to update the table.
I currently have this query written but it throws the error:
ORA-01427: single-row subquery returns more than one row
UPDATE TAB_A t1
SET (V_TILL) = (SELECT TO_DATE(t2.D_DATE,'YYYYMMDD')
FROM B t2
WHERE t1.BR_CODE = t2.BR_CODE
AND t1.BK_CODE = t2.BK_CODE||t2.BR_CODE)
WHERE EXISTS (
SELECT 1
FROM TAB_B t2
WHERE t1.BR_CODE = t2.BR_CODE
AND t1.BK_CODE = t2.BK_CODE||t2.BR_CODE)
PS: BK_CODE IS THE CONCATENATION OF BK_CODE and BR_CODE
Kindly help me as I am stuck in this quagmire! Any help would be appreciated.
If the subquery returns many values which one do you want to use ?
If any you can use rownum <=1;
If you know that there is only one value use distinct
SET (V_TILL) = (SELECT TO_DATE(t2.D_DATE,'YYYYMMDD')
FROM B t2
WHERE t1.BR_CODE = t2.BR_CODE
AND t1.BK_CODE = t2.BK_CODE||t2.BR_CODE AND ROWNUM <=1)
or
SET (V_TILL) = (SELECT DISTINCT TO_DATE(t2.D_DATE,'YYYYMMDD')
FROM B t2
WHERE t1.BR_CODE = t2.BR_CODE
AND t1.BK_CODE = t2.BK_CODE||t2.BR_CODE)
above are workarounds. To do it right you have to analyze why you are getting more than one value. Maybe more sophisticated logic is needed to select the right value.
I got it working with this command:
MERGE INTO TAB_A A
USING TAB_B B
ON (A.BK_CODE = B.BK_CODE || B.BR_CODE
AND A.BR_CODE = B.BR_CODE AND B.BR_DISP_TYPE <> '0'
AND ((B.BK_CODE, B.BR_SUFFIX) IN (SELECT BK_CODE,
MIN(BR_SUFFIX)
FROM TAB_B
GROUP BY BK_CODE)))
As mentioned earlier by many, I was missing an extra condition and got it working, otherwise the above mentioned techniques work very well.
Thanks to all!

Excluding a Null value returns 0 rows in a sub query

I'm trying to clean up some data in SQL server and add a foreign key between the two tables.
I have a large quantity of orphaned rows in one of the tables that I would like to delete. I don't know why the following query would return 0 rows in MS SQL server.
--This Query returns no Rows
select * from tbl_A where ID not in ( select distinct ID from tbl_B
)
When I include IS NOT NULL in the subquery I get the results that I expect.
-- Rows are returned that contain all of the records in tbl_A but Not in tbl_B
select * from tbl_A where ID not in ( select distinct ID from tbl_B
where ID is not null )
The ID column is nullable and does contain null values. IF I run just the subquery I get the exact same results except the first query returns one extra NULL row as expected.
This is the expected behavior of the NOT IN subquery. When a subquery returns a single null value NOT IN will not match any rows.
If you don't exclusively want to do a null check, then you will want to use NOT EXISTS:
select *
from tbl_A A
where not exists (select distinct ID
from tbl_B b
where a.id = b.id)
As to why the NOT IN is causing issues, here are some posts that discuss it:
NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL
NOT EXISTS vs NOT IN
What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?
Matching on NULL with equals (=) will return NULL or UNKNOWN as opposed to true/false from a logic standpoint. E.g. see http://msdn.microsoft.com/en-us/library/aa196339(v=sql.80).aspx for discussion.
If you want to include finding NULL values in table A where there is no NULL in table B (if B is the "parent" and A is the "child" in the "foreign key" relationship you desire) then you would need a second statement, something like the following. Also I would recommend qualifying the ID field with a table prefix or alias since the field names are the same in both tables. Finally, I would not recommend having NULL values as the key. But in any case:
select * from tbl_A as A where (A.ID not in ( select distinct B.ID from tbl_B as B ))
or (A.ID is NULL and not exists(select * from tbl_B as B where B.ID is null))
The problem is the non-comparability of nulls. If you are asking "not in" and there are nulls in the subquery it cannot say that anything anything is definitely not in becuase it is looking at those nulls as "unknown" and so the answer is always "unknown" in the three value logic that SQL uses.
Now of course that is all assuming you have ANSI_NULLS ON (which is the default) If you turn that off then suddenly NULLS become comparable and it will give you results, and probably the results you expect.
If the ids are never negative, you might consider something like:
select *
from tbl_A
where coalesce(ID, -1) not in ( select distinct coalesce(ID, -1) from tbl_B )
(Or if id is a string, use something line coalesce(id, '<null>')).
This may not work in all cases, but it has the virtue of simplicity on the coding level.
You probably have ANSI NULLs switched off. This compares null values so null=null will return true.
Prefix the first query with
SET ANSI_NULLS ON
GO

Use of CASE statement values in THEN expression

I am attempting to use a case statement but keep getting errors. Here's the statement:
select TABLE1.acct,
CASE
WHEN TABLE1.acct_id in (select acct_id
from TABLE2
group by acct_id
having count(*) = 1 ) THEN
(select name
from TABLE3
where TABLE1.acct_id = TABLE3.acct_id)
ELSE 'All Others'
END as Name
from TABLE1
When I replace the TABLE1.acct_id in the THEN expression with a literal value, the query works. When I try to use TABLE1.acct_id from the WHEN part of the query, I get a error saying the result is more than one row. It seems like the THEN expression is ignoring the single value that the WHEN statement was using. No idea, maybe this isn't even a valid use of the CASE statement.
I am trying to see names for accounts that have one entry in TABLE2.
Any ideas would be appreciated, I'm kind of new at SQL.
First, you are missing a comma after TABLE1.acct. Second, you have aliased TABLE1 as acct, so you should use that.
Select acct.acct
, Case
When acct.acct_id in ( Select acct_id
From TABLE2
Group By acct_id
Having Count(*) = 1 )
Then ( Select name
From TABLE3
Where acct.acct_id = TABLE3.acct_id
Fetch First 1 Rows Only)
Else 'All Others'
End as Name
From TABLE1 As acct
As others have said, you should adjust your THEN clause to ensure that only one value is returned. You can do that by add Fetch First 1 Rows Only to your subquery.
Then ( Select name
From TABLE3
Where acct.acct_id = TABLE3.acct_id
Fetch First 1 Rows Only)
Fetch is not accepting in CASE statement - "Keyword FETCH not expected. Valid tokens: ) UNION EXCEPT. "
select name from TABLE3 where TABLE1.acct_id = TABLE3.acct_id
will give you all the names in Table3, which have a accompanying row in Table 1. The row selected from Table2 in the previous line doesn't enter into it.
Must be getting more than one value.
You can replace the body with...
(select count(name) from TABLE3 where TABLE1.acct_id = TABLE3.acct_id)
... to narrow down which rows are returning multiples.
It may be the case that you just need a DISTINCT or a TOP 1 to reduce your result set.
Good luck!
I think that what is happening here is that your case must return a single value because it will be the value for the "name" column. The subquery (select acct_id from TABLE2 group by acct_id having count(*) = 1 ) is OK because it will only ever return one value. (select name from TABLE3 where TABLE1.acct_id= TABLE3.acct_id) could return multiple values depending on your data. The problem is you trying to shove multiple values into a single field for a single row.
The next thing to do would be to find out what data causes multiple rows to be returned by (select name from TABLE3 where TABLE1.acct_id= TABLE3.acct_id), and see if you can further limit this query to only return one row. If need be, you could even try something like ...AND ROWNUM = 1 (for Oracle - other DBs have similar ways of limiting rows returned).