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.
Related
I want to see all my customers who have received a document code Eg. [RF001], however I also want to see that they haven't received a number of document codes E.G [RF002, RF005, RF006, RF009].
All the document codes sit in 1 column, and the customer references are repeated.
Table
Customer_Ref | Doc_Code
CS001 | RF001
CS002 | RF003
CS001 | RF002
Code thats been tried is;
SELECT *
FROM Test_Data
WHERE Doc_Code = RF001
You can use NOT EXISTS to exclude unwanted results :
SELECT *
FROM Table1 tbl
WHERE
Doc_Code='RF001'
AND NOT EXISTS (SELECT 1
FROM Table1 unwanted
WHERE
tbl.Customer_Ref=unwanted.Customer_Ref
AND Doc_Code IN ('RF002', 'RF005', 'RF006', 'RF009'))
SELECT *
FROM Test_Data t1
WHERE t1.Doc_Code = 'RF001'
and not exists (select 1 from Test_Data t2
where t1.Customer_Ref = t2.Customer_Ref
and t2.Doc_Code in ('RF002', 'RF005', 'RF006', 'RF009')
There's several ways to accomplish this.
This is but one way using a join
SELECT Distinct A.CUSTOMER_REF
FROM TABLE A
LEFT JOIN (SELECT DISINTCT CUSTOMER_REF
FROM TABLE B
WHERE B.DOC_CODE IN ('RF002', 'RF005', 'RF006', 'RF009') B
ON A.CUSTOMER_REF = B.CUSTOMER_REF
WHERE A.DOC_CODE = 'RF001'
and B.Customer_REF is null
Another way is to use not exists (I'm sure someone else will do)
Another way is to use a not in (I'm sure someone else will do)
Another way is to use set logic and EXCEPT (Similar to a Union; but subtracts once set from another)
.
SELECT A.Customer_REF FROM table where DOC_CODE = 'RF001'
EXCEPT
SELECT A.Customer_REF FROM Table where DOC_CODE IN ('RF002', 'RF005', 'RF006', 'RF009')
Should be simple enough I think but I'm not getting it and I'm not sure how to explain it without an example to look it up.
Table:
1. A B
2. null 1
3. null null
4. 1 null
5. 1 1
I want my query to omit anything where both column A and B are null (in example, row 3 would be omitted).
select * from Table where (A is not null) and (B is not null)
Is just giving me columns where both are present.
Any help would be great.
*edit: changed "return" to "omit"
You can filter like this:
select * from Table where nvl(A,B) is not null
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.
Think of this table:
____________
| ID | Value |
| 1 | One |
| 3 | Three |
If I run a query like this SELECT Value FROM myTable WHERE ID = 1 I'm sure to get its appropiate value, be it One in this case, but if I change the ID to any other number non existant on that table, I will get nothing on the Value column, of course, since there wouldn't be any data there.
But is there a way to make Sql Server return at least an empty space when doing such queries?
Sql Fiddle with same case: http://sqlfiddle.com/#!3/f30f8/2
select Value
from YourTable
where ID = 1
union all
select null
where not exists
(
select *
from YourTable
where ID = 1
)
So yes, it's technically possible, but you can see why this is much easier solved in a general purpose language.
Yes. You can do this:
select coalesce(max(value), '')
from test t
where id = 1;
The idea is that max() always returns a value. It will be NULL if there is no match, and you can replace that with an empty string (or whatever).
I have two tables, one an import table, the other a FK constraint on the table the import table will eventually be put into. In the import table a user can provide a list of semicolon separated values that correspond to values in the 2nd table.
So we're looking at something like this:
TABLE 1
ID | Column1
1 | A; B; C; D
TABLE 2
ID | Column2
1 | A
2 | B
3 | D
4 | E
The requirement is:
Rows in TABLE 1 with a value not in TABLE 2 (C in our example) should be marked as invalid for manual cleanup by the user. Rows where all values are valid are handled by another script that already works.
In production we'll be dealing with 6 columns that need to be checked and imports of AT LEAST 100k rows at a time. As a result I'd like to do all the work in the DB, not in another app.
BTW, it's SQL2008.
I'm stuck, anyone have any ideas. Thanks!
Seems to me you could pass ID & Column1 values from Table1 to a Table-Valued function (or a temp table in-line) which would parse the ;-delimited list, returning individual values per record.
Here are a couple options:
T-SQL: Parse a delimited string
Quick T-Sql to parse a delimited string
The result (ID, value) from the function could be used to compare (unmatched query) against values in Table 2.
SELECT tmp.ID
FROM tmp
LEFT JOIN Table2 ON Table2.id = tmp.ID
WHERE Table2.id is null
The ID results of the comparison would then be used to flag records in Table 1.
Perhaps inserting those composite values into 'TABLE 1' may have seemed like the most convenient solution at one time. However, unless your users are using SQL Server Management Studio or something similar to enter the values directly into the table then I assume there must be a software layer between the UI and the database. If so, you're going to save yourself a lot headaches both now and in the long run by investing a little time in altering your code to split the semi-colon delimited inputs into discrete values before inserting them into the database. This will result in 'TABLE 1' looking something like this
TABLE 1
ID | Column1
1 | A
1 | B
1 | C
1 | D
It's then trivial to write the SQL to find those IDs which are invalid.
If it is possible, try putting the values in separate rows when importing (instead of storing it as ; separated).
This might help.
Here is an easy and straightforward solution for the IDs of the invalid rows, despite its lack of performance because of string manipulations.
select T1.ID
from [TABLE 1] T1
left join [TABLE 2] T2
on ('; ' + T1.COLUMN1 + '; ') like ('%; ' + T2.COLUMN2 + '; %')
where T1.COLUMN1 is not null
group by T1.ID
having count(*) < len(T1.COLUMN1) - len(replace(T1.COLUMN1, ';', '')) + 1
There are two assumptions:
The semicolon-separated list does not contain duplicates
TABLE 2 does not contain duplicates in COLUMN2.
The second assumption can easily be fixed by using (select distinct COLUMN2 from [TABLE 2]) rather than [TABLE 2].