SQL to join two tables with one where clause on one table - sql

I have two tables as the following
table1
main_id main_val main_sub main_pk
1 A NULL 3
3 A 1 3
table2
col_id col_val
1 A
select table1.main_pk from table1 ,table2 WHERE
table1.main_id = table2.col_id
and table1.main_val = table2.col_val
and table1.main_sub = null
Am expecting the above query to select the first row in table 1 as main_sub is null and the other two columns matches. But it does not. I am just learning SQL basics so am not sure where am going wrong. Please help

I didn't fully understand the question but I think this is what you want:
SELECT * from table1 INNER JOIN table2 on table1.main_val=table2.main_val WHERE table1.main_sub IS NULL
If not I think it directs you in the right path

SQL is a little weird about NULL values. Use the condition
....
table1.main_sub IS NULL
for testing for a null specifically. The idea is that NULL is supposed to be interpreted as nothing, so nothing -equals- nothing can't ever be true because you can't compare something that doesn't exist.

Related

Subtraction giving null in postgres

I've a table temp(id int,name text) and another table temp2(id int,times int). temp stores (1,'a'),(2,'b') and (3,'c'). temp2 stores (1,1) and (2,2). I want to find the difference between the id of a character and the number of times it comes. Because 'c' doesn't appear in the temp2 column, its times is null. Further, please note that I can't edit the given tables in any way. Here's what I did:-
SELECT name, temp.id,
CASE WHEN times=null THEN temp.id
ELSE temp.id-times
END
FROM temp LEFT OUTER JOIN temp2
ON (temp.id=temp2.id);
But, the problem with this is that it still gives me this output:-
name | id | case
------+----+------
a | 1 | 0
b | 2 | 0
c | 3 |
(3 rows)
(Note that case is null for c). Please help me solve this issue. Thanks!
Use coalesce():
SELECT name, temp.id,
temp.id - COALESCE(times, 0)
FROM temp LEFT OUTER JOIN
temp2
ON temp.id = temp2.id;
Your specific problem is the comparison = NULL. The correct method would be IS NULL. Nothing can be "equal" to NULL in SQL, so that never returns TRUE.
However, COALESCE() is a simpler way to express the logic.

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!

Sql server Update Query in table with duplicate records

I would like to know what happen when I do an update with duplicated rows, for example:
Table 1:
Email StatusID Status
phil#gmail.com NULL
dome#yahoo.es 1 Busy
phil#gmail.com 2 Online
dome#yahoo.es NULL
Table 2:
Email Name RejectionStatusID RejectionStatus
dome#yahoo.es Dome 1
phil#gmail.com Phil 2
Result?
Update Table2
SET RejectionStatusID = StatusID,
RejectionStatus = Status
FROM Table2 Inner Join Table1
ON Table2.Email = Table1.Email
I wouldlike to know which of the duplicated and why??? Not really sure!!! Of course I did the query and know what happen but why? Just want an explanation...
Thanks.
EDITED:
This is the example, this is what happen with null values!!!
http://sqlfiddle.com/#!6/6ee69/1/0
From BoL https://msdn.microsoft.com/en-us/library/ms177523(v=sql.110).aspx
The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic.

Matching records with wild cards from two different tables

I have two tables with the following data (amongst other data).
Table 1
Value 1
'003232339639
'00264644106272
0026461226291#
I need to match the second column in the table below using column 1 as an identifier
Table 2
Value 1 Value 2
00264 1
0026485 2
0026481 3
00322889 4
00323283 5
00323288 6
So the results I need will be as follows:
Result
Table 1, Value 1 Table 2, Value 2
'003232339639......4
'00264644106272....1
0026461226291#.....1
Any help will be appreciated - very stuck here and doing it manually at the moment in excel.
I hope this format makes sense - first time I am using this forum.
Melany, the question is kind of confusing (not written correctly) perhaps that's why no one is responding. I'll make an attempt to explain how similar selects is done
SELECTING DATA FROM TABLE1 WHERE A MATCHING COLUMN (COL1) EXISTS IN BOTH TABLE
SELECT * FROM TABLE1
INNER JOIN TABLE2
ON TABLE1.COL1 = TABLE2.COL1
AND TABLE1.COL1 = 'XYZ'
USING A SUBSELECT FOR THE SAME
SELECT * FROM TABLE1
WHERE COL1 IN(SELECT COL1 FROM TABLE2
WHERE COL1 = 'XYZ')
In SQL, the wildcard for one or more characters is %, and is to be used with the keyword LIKE.
So I suggest the following (if your purpose is really to match rows in Table1 for which Value1 begins like a value in Table2.Value1):
SELECT Table1.Value1, Table2.Value2 WHERE Table1.Value1 LIKE CONCAT(Table2.Value1, '%');
Edit: replace CONCAT(x, y) with x || y for some DBMSs (SQLite for instance).

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).