How to set default value with "IN" statment, like this:
SELECT username
FROM user
WHERE id IN (1,2,3,4)
ORDER BY FIELD(id,1,2,3,4)
If id = 2 is not available then return 0 or null, like this:
John33
0
amanda1
erik
You need to do this with a left join:
SELECT u.username
FROM (select 1 as id union all select 2 union all select 3 union all select 4
) ids left join
user u
on u.id = ids.id
ORDER BY FIELD(id, 1, 2, 3, 4);
Logic in the where clause cannot "add" new rows to the result set.
An IN (list) comparison returns a boolean, (TRUE, FALSE or NULL) for every row it's evaluated for.
So, a foo IN (list) cannot (by itself) "produce" a row that's not available in the row source.
(You say that id = 2 "is not available", we take that to mean that there is no row in user that satisfies that predicate.)
You could produce the resultset as shown, but it doesn't require an IN comparison at all.
You need a rowsource that is guaranteed to return the "id" values you want; an inline view is a convenient way to do that.
SELECT u.username
FROM ( SELECT 1 AS id
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
) n
LEFT
JOIN user u
ON u.id = n.id
ORDER BY n.id
The LEFT JOIN specifies an outer join operation. That is, if there is no matching row from the table on the right side (user) that matches a row from the table on the left side (n), then the query will return the row from n along with NULL values for all the columns from user.
You can replace that NULL value for username replaced using an expression in the SELECT list. Check if u.id is NULL (which would mean there was no matching row found), and return something else. For example, the literal 0.
SELECT IF(u.id IS NULL,'0',u.username) AS username
That's MySQL specific syntax for the ANSI-standard equivalent
SELECT CASE WHEN u.id IS NULL THEN '0' ELSE u.username END AS username
If you want to replace all NULL values of username, not just NULL values produced when a user row is missing:
SELECT IFNULL(u.username,'0') AS username
Related
So, I have this sql:
SELECT program.BilanganTerhad - IFNULL(COUNT(daftarprogram.KodProgram), 0) AS kiraan
FROM program, daftarprogram
WHERE program.KodProgram = daftarprogram.KodProgram
AND daftarprogram.KodProgram = '19'
How can I set the null COUNT() value to 0? For example: 10 - null = null instead of 10 - 0 = 10.
I need the count become 0, not null.
This is value from table1
While this is value from table2
I want to subtract value from table1 and minus with count(kodprogram)
The thing is I want to subtract value from table1 with count(KodProgram) from table2 based on where condition = KodProgram
COUNT() never returns NULL. That said, your query is malformed (in addition to using archaic join syntax. BilanganTerhad is in the SELECT but it is an aggregation query.
Perhaps you intend:
SELECT p.BilanganTerhad - COUNT(*) AS kiraan
FROM program p JOIN
daftarprogram dp
ON p.KodProgram = dp.KodProgram
WHERE dp.KodProgram = '19'
GROUP BY p.BilanganTerhad;
I have a query like this . I have compound index for CC.key1,CC.key2.
I am executing this in a big database
Select * from CC where
( (
(select count(*) from Service s
where CC.key1=s.sr2 and CC.key2=s.sr1) > 2
AND
CC.key3='new'
)
OR
(
(select count(*) from Service s
where CC.key1=s.sr2 and CC.key2=s.sr1) <= 2
)
)
limit 10000;
I tried to make it as inner join , but its getting slower . How can i optimize this query ?
The trick here is being able to articulate a query for the problem:
SELECT *
FROM CC t1
INNER JOIN
(
SELECT cc.key1, cc.key2
FROM CC cc
LEFT JOIN Service s
ON cc.key1 = s.sr2 AND
cc.key2 = s.sr1
GROUP BY cc.key1, cc.key2
HAVING COUNT(*) <= 2 OR
SUM(CASE WHEN cc.key = 'new' THEN 1 ELSE 0 END) > 2
) t2
ON t1.key1 = t2.key1 AND
t1.key2 = t2.key2
Explanation:
Your original two subqueries would only add to the count if a given record in CC, with a given key1 and key2 value, matched to a corresponding record in the Service table. The strategy behind my inner query is to use GROUP BY to count the number of times that this happens, and use this instead of your subqueries. The first count condition is your bottom subquery, and the second one is the top.
The inner query finds all key1, key2 pairs in CC corresponding to records which should be retained. And recognize that these two columns are the only criteria in your original query for determining whether a record from CC gets retained. Then, this inner query can be inner joined to CC again to get your final result set.
In terms of performance, even this answer could leave something to be desired, but it should be better than a massive correlated subquery, which is what you had.
Basically get the Columns that must not have a duplicate then join them together. Example:
select *
FROM Table_X A
WHERE exists (SELECT 1
FROM Table_X B
WHERE 1=1
and a.SHOULD_BE_UNIQUE = b.SHOULD_BE_UNIQUE
and a.SHOULD_BE_UNIQUE2 = b.SHOULD_BE_UNIQUE2
/* excluded because these columns are null or can be Duplicated*/
--and a.GENERIC_COLUMN = b.GENERIC_COLUMN
--and a.GENERIC_COLUMN2 = b.GENERIC_COLUMN2
--and a.NULL_COLUMN = b.NULL_COLUMN
--and a.NULL_COLUMN2 = b.NULL_COLUMN2
and b.rowid > a.ROWID);
Where SHOULD_BE_UNIQUE and SHOULD_BE_UNIQUE2 are columns that shouldn't be repeated and have unique columns and the GENERIC_COLUMN and NULL_COLUMNS can be ignored so just leave them out of the query.
Been using this approach when we have issues in Duplicate Records.
With the limited information you've given us, this could be a rewrite using 'simplified' logic:
SEELCT *
FROM CC NATURAL JOIN
( SELECT key1, key2, COUNT(*) AS tally
FROM Service
GROUP
BY key1, key2 ) AS t
WHERE key3 = 'new' OR tally <= 2;
Not sure whether it will perform better but might give you some ideas of what to try next?
I have a populated table with a 'Number' as PK. I would like a query which searches for a specific number, and if it is not found then it would return "NULL" not a no value.
I have managed to do it for one return:
SELECT (SELECT Risk_Impact FROM [dbo].[RFC] WHERE Number = 'RFC-018345')
However I would like to select multiple columns like:
SELECT (SELECT Risk_Impact, Risk_Impact, BI_TestingOutcome FROM [dbo].[RFC] WHERE Number = 'RFC-018345')
However it is giving me an error:
"Msg 116, Level 16, State 1, Line 1
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."
Can you please assist?
Thank you in advance
Try
select p.* from (select 1 as t ) v
left join (select * from [dbo].[RFC] WHERE Number = 'RFC-018345') p
on 1=1
In sql server should be use isnull function like this
SELECT isnull((SELECT Risk_Impact FROM [dbo].[RFC] WHERE Number = 'RFC-018345'),0)
Refined #Sagar query:
And better indentation would probably be more helpful for people to learn from.
Ex:
SELECT
[dbo].[RFC].*
FROM
(SELECT 1 AS Col1) AS V
CROSS JOIN
[dbo].[RFC]
WHERE Number = 'RFC-018345'
Edit: I got caught up in removing the subquery. Working query:
SELECT
[dbo].[RFC].*
FROM
(SELECT 1 AS Col1) AS V
LEFT JOIN
[dbo].[RFC]
ON Number = 'RFC-018345'
(I would also advocate to not SELECT *, anywhere near production, but to always be explicit about the columns in the result set. Ex:
SELECT
[dbo].[RFC].[Risk_Impact],
[dbo].[RFC].[BI_TestingOutcome]
FROM
(SELECT 1 AS Col1) AS V
LEFT JOIN
[dbo].[RFC]
ON Number = 'RFC-018345'
)
I am running a query like this:
select x from table where c in ('variable','test','ok')
I get the results for all the matching C. (variable and test)
But because ok doesn't exist in c I don't get anything. Not even a null or 0 result.
How can I say to mysql that I want a result even if it doesn't find a match for a term in the in condition?
example:
result
x = 12
x = 25
x = NOT FOUND
Thanks in advance
I'm not sure if I understand the problem, but I guess you mean that you want X column value if c in ('variable','test','ok'), and if not, you want 'NOT FOUND'?
Move the IN condition from the WHERE clause to the select list:
select case when c in ('variable','test','ok') then x
else 'NOT FOUND' end
from table
Or, perhaps you mean that if no rows at all returned, you want one single 'NOT FOUND' row? Do UNION ALL with that row.
select x from table where c in ('variable','test','ok')
UNION ALL
select 'NOT FOUND'
from (select count(*) as cnt from table
where c in ('variable','test','ok') t
where cnt = 0
The usual approach for this is an outer join that joins a subquery for your fixed data and your actual table:
select v1.name, coalesce(t.x, 'NOT FOUND')
from (
select 'variable' as name union all
select 'test' union all
select 'x') v1
left join t on t.c = v1.name
SQL Fiddle
My MySQL table looks like the following:
I would like to get results where all the followings are satisfied:
form_id is 1
sort by lead_id high to low
field_number 9 for that lead_id must be 111
In summary, my query should return 9 rows. Is that possible?
Here is my attempt so far, but I really want to avoid using GROUP_CONCAT if at all possible to get a cleaner result set.
SELECT lead_id, GROUP_CONCAT(field_number, "|", value SEPARATOR "----") AS `values`
FROM lead_detail
WHERE form_id = 1
GROUP BY lead_id
ORDER BY lead_id DESC
If you are meaning that you want to include only rows for a lead_id if there exists a row for that lead_id with field_number=9 and value=111. And otherwise, all rows for that lead_id should be excluded...
You could do something like this:
SELECT d.id
, d.lead_id
, d.form_id
, d.field_number
, d.value
FROM ( SELECT e.lead_id
FROM lead_detail e
WHERE e.form_id = 1
AND e.field_number = 9
AND e.value = 111
GROUP BY e.lead_id
) f
JOIN lead_detail d
ON d.lead_id = f.lead_id
AND d.form_id = 1
ORDER BY d.lead_id DESC
The inline view (aliased as f) returns a distinct list of lead_id that meet specific criteria. We can reference the result from that like it were a table, and use that in a JOIN operation, to return "matching" rows from the lead_detail table. (If there's no row with value=111, field_number=9, and form_id=1 for a particular lead_id, then the inline view won't return that lead_id in the list.)
As another alternative, we could use an EXISTS predicate with a correlated subquery, but this may not perform as well:
SELECT d.id
, d.lead_id
, d.form_id
, d.field_number
, d.value
FROM lead_detail d
WHERE d.form_id = 1
AND EXISTS
( SELECT 1
FROM lead_detail e
WHERE e.form_id = 1
AND e.field_number = 9
AND e.value = 111
AND e.lead_id = d.lead_id
)
ORDER BY d.lead_id DESC
That essentially says, for every row from lead_detail run the subquery following the EXIST keyword... if the subquery returns one (or more) rows, then the EXISTS predicate returns TRUE, otherwise it returns FALSE. That subquery is "correlated" to the outer query, by a predicate in the WHERE clause, matching the lead_id to the value of lead_id from the row from the outer query.
The short answer is "not easily." There are a couple of ways to do this that aren't super straightforward -- probably the easiest is with a sub-query (the exact format will change depending on the exact format of your table, etc.)
SELECT lead_id, GROUP_CONCAT(field_number, "|", value SEPARATOR "----") AS `values`
FROM lead_detail
WHERE `form_id` = 1
AND `lead_id` = (SELECT `lead_id` FROM `lead_detail` WHERE `field_number` = 9 AND `value` = 111 AND `form_id` = 1) /*This is the subquery*/
GROUP BY lead_id
ORDER BY lead_id DESC
Other options include running two separate queries, one to pull the form_id (or form_ids) in question, the other to pull all data for that form_id (or those form_ids).