I want my DB to return row under one of two conditions:
The row contains specific value "val" and is of type "sometype"
There is other row, that does have the type "sometype" and the same name as currently checked row.
For this purpose, I made a folowing query:
SELECT c.name, c.value, c.type
FROM `table` AS c
WHERE
c.type='sometype' AND c.value='val'
OR
c.type='othertype' AND
0<(SELECT count(*) FROM `table` AS d WHERE d.name=c.name and c.name='sometype')
Unfortunately, this will return all rows of 'othertype'. I only want these, that have friend with same name and type 'sometype'.
I think the problem is, that I don't know how to get the reference to the values in curently checked row (which I believed to be c.fieldname). I believed d.name = c.name would return all rows that have same name as currently checked row. But the nested select is always >0.
I think this should work for what you are doing:
SELECT c.name, c.type, c.value
FROM test as c
INNER JOIN (SELECT name, type
FROM test
WHERE type = "type1"
AND value = 3) as d
ON c.name = d.name AND c.type = d.type;
SQLFiddle: http://sqlfiddle.com/#!2/63255/1
The inner select gets your #1, where type="sometype" and value="val". Then the outer gets the names, types and values that correspond to the name and type of the inner select, which is your #2.
SELECT c.name
, c.value
, c.type
FROM table c
WHERE (c.type = 'sometype' AND c.value = 'val')
OR (c.type = 'othertype' AND 0< (SELECT COUNT(*) FROM `table` d WHERE d.name = c.name AND c.name='sometype'));
also consider rewriting without the subquery
Related
My query has multiple column being selected but now i want when no returned I want some dummy value to be returned.
For example in the following query:
SELECT a.abc, b.def, c.ghi
FROM comp a, damp b, champ c, omp d
WHERE a.id=b.id
and b.id=c.id
and c.id= d.id
ORDER BY a.abc desc
if there is no row returned I wanted to display atleast one column with some value, can somebody suggest me how can I achieve this.
I have already gone through some suggestion but none worked. Any help would be appreciated.
In oracle you could do something like this:
WITH mybigselect AS
(
SELECT a.abc, b.def, c.ghi
FROM comp a
JOIN damp b ON a.id = b.id
JOIN champ c ON b.id = c.id
JOIN omp d ON c.id = d.id
ORDER BY a.abc desc
)
SELECT * FROM mybigselect
UNION ALL
SELECT 'Nothing found', NULL, NULL FROM mybigselect
WHERE NOT EXISTS (SELECT * FROM mybigselect)
Note 1: that both rows in the UNION ALL needs to return columns of the same datatype. You can't return a number in the first column of SELECT * FROM mybigselect and "nothing found" in the query after UNION ALL
Note 2: rewrote the query using ANSI-JOIN style syntax.
I would recommend:
WITH cte as (
SELECT a.abc, b.def, c.ghi
FROM comp do JOIN
damp d
ON d.id = co.id JOIN
champ c
ON ch.id = d.id
omp o
ON o.id = ch.id
)
SELECT *
FROM cte
UNION ALL
SELECT 'Some value', NULL, NLL
FROM dual
WHERE NOT EXISTS (SELECT 1 FROM cte)
ORDER BY abc DESC;
Notes:
The value has to be compatible with the type of the column. So, if abc is not a string, then 'Some value' is not appropriate. You haven't provided enough information to determine what value should be in which column.
The ORDER BY should be in the outermost query, not the CTE.
Never use comas in the FROM clause. Always use proper, explicit, standard, readable JOIN syntax.
This version uses meaningful table aliases (table name abbreviations) rather than arbitrary letters.
I am running a SELECT query to return addresses in a table associated with a certain "applicant code" and I'd like to join a table to also return (in the same row) the name of that applicant.
Therefore my query as of now is
SELECT a.id, a.created_at, a.updated_at, a.code, a.applicant_code, a.form_code, a.address_line_1, a.address_line_2, a.town_city, a.county_state, a.country, a.post_code, a.start_date, a.end_date, a.type, ap.first_name, ap.last_name
FROM sfs_addresses a
JOIN sfs_personal_details ap ON a.form_code = ap.form_code
WHERE a.form_code = ? AND a.applicant_code = ?
The query works, and I get the right columns and values in each row, but it returns 2 of each so like
ID
===
1
1
2
2
3
3
4
4
If I remove the JOIN it works fine. I have tried adding DISTINCT (makes no difference) I'm lost.
EDIT: Based on this answer and the comments, the OP realized that the JOIN condition should be on applicant_code rather than form_code.
You have duplicates in the second table based on the JOIN key you are using (I question if the JOIN is correct).
If you just want one row arbitrarily, you can use row_number():
SELECT a.*, ap.first_name, ap.last_name
FROM sfs_addresses a JOIN
(SELECT ap.*,
ROW_NUMBER() OVER (PARTITION BY ap.form_code ORDER BY ap.form_code) as seqnum
FROM sfs_personal_details ap
) ap
ON a.form_code = ap.form_code
WHERE a.form_code = ? AND a.applicant_code = ?;
You can replace the columns in the ORDER BY with which result you want -- for instance the oldest or most recent.
Note: form_code seems like an odd JOIN column for a table called "personal details". So, you might just need to fix the JOIN condition.
relation between 2 tables one to many to return non duplicate use distinct
SELECT distinct a.id, a.created_at, a.updated_at, a.code, a.applicant_code, a.form_code, a.address_line_1, a.address_line_2, a.town_city, a.county_state, a.country, a.post_code, a.start_date, a.end_date, a.type, ap.first_name, ap.last_name
FROM sfs_addresses a
JOIN sfs_personal_details ap ON a.form_code = ap.form_code
WHERE a.form_code = ? AND a.applicant_code = ?
I have 3 tables with following columns.
Table: A with column: newColumnTyp1, typ2
Table: B with column: typ2, tableC_id_fk
Table: C with column: id, typ1
I wanted to update values in A.newColumnTyp1 from C.typ1 by following logic:
if A.typ2=B.typ2 and B.tableC_id_fk=C.id
the values must be distinct, if any of the conditions above gives multiple results then should be ignored. For example A.typ2=B.typ2 may give multiple result in that case it should be ignored.
edit:
the values must be distinct, if any of the conditions above gives multiple results then take only one value and ignore rest. For example A.typ2=B.typ2 may give multiple result in that case just take any one value and ignore rest because all the results from A.typ2=B.typ2 will have same B.tableC_id_fk.
I have tried:
SELECT DISTINCT C.typ1, B.typ2
FROM C
LEFT JOIN B ON C.id = B.tableC_id_fk
LEFT JOIN A ON B.typ2= A.typ2
it gives me a result of table with two columns typ1,typ2
My logic was, I will then filter this new table and compare the type2 value with A.typ2 and update A.newColumnTyp1
I thought of something like this but was a failure:
update A set newColumnTyp1= (
SELECT C.typ1 from
SELECT DISTINCT C.typ1, B.typ2
FROM C
LEFT JOIN B ON C.id = B.tableC_id_fk
LEFT JOIN A ON B.typ2= A.type2
where A.typ2=B.typ2);
I am thinking of an updateable CTE and window functions:
with cte as (
select a.newColumnTyp1, c.typ1, count(*) over(partition by a.typ2) cnt
from a
inner join b on b.type2 = a.typ2
inner join c on c.id = b.tableC_id_fk
)
update cte
set newColumnTyp1 = typ1
where cnt > 1
Update: if the columns have the same name, then alias one of them:
with cte as (
select a.typ1, c.typ1 typ1c, count(*) over(partition by a.typ2) cnt
from a
inner join b on b.type2 = a.typ2
inner join c on c.id = b.tableC_id_fk
)
update cte
set typ1 = typ1c
where cnt > 1
I think I would approach this as:
update a
set newColumnTyp1 = bc.min_typ1
from (select b.typ2, min(c.typ1) as min_typ1, max(c.typ1) as max_typ1
from b join
c
on b.tableC_id_fk = c.id
group by b.type2
) bc
where bc.typ2 = a.typ2 and
bc.min_typ1 = bc.max_typ1;
The subquery determines whether typ1 is always the same. If so, it is used for updating.
I should note that you might want the most common value assigned, instead of requiring unanimity. If that is what you want, then you can ask another question.
I am not sure if my method is possible, but i'm trying to do a group_concat on a select statement that concats 2 fields. I get the error: Subquery returns more than 1 row each time. Can anyone help me as to a solution, or better way around this.
select t.recnum, (select group_concat((select concat(b.origtests,'^', d.name) as testing
from order_origtests b
join profile c on c.code = b.origtests
join department d on d.recnum = c.dept
)))
FROM order_ t
You don't put SELECT inside GROUP_CONCAT. It should be
select t.recnum, (
select group_concat(concat(b.origtests,'^', d.name))
from order_origtests b
join profile c on c.code = b.origtests
join department d on d.recnum = c.dept
) AS testing
FROM order_ t
Note that your subquery isn't correlated to anything in t, so you'll get the same testing column for every recnum.
If I have the schemas:
Type(a,b,c,d)
Name(e, b, g)
I am trying to find all the resulting Name's 'E' where the 'D' of the Type is greater than a number that we access using the shared 'B'.
I am trying to understand how to have multiple SELECT statements such as:
SELECT e FROM Name WHERE b = (SELECT b FROM Type WHERE d > 1);
Can someone explain the syntax error and how to do nested SELECT statements or do I have to join the two tables.
Thanks
This can be accomplished using a simple INNER JOIN operation:
SELECT DISTINCT n.e
FROM Name AS n
INNER JOIN Type AS t ON n.b = t.b
WHERE t.d > 1
You can also use EXISTS:
SELECT n.e
FROM Name AS n
WHERE EXISTS (SELECT 1
FROM Type AS t
WHERE n.b = t.b AND t.d > 1)
I think you want to use IN instead of =
SELECT e FROM Name WHERE b IN (SELECT b FROM Type WHERE d > 1);
= to compare one value to another value.
IN to see if a value exist whiten a list of multiple values.