concat() with select query? - mysql

I need to use a concat function which has an argument returned by select query like this
CONCAT(classification_version.NAME,' ',
(select x.NAME,min(DATEDIFF(e.SEND_DATE, x.OPTENTION_DATE))
AS DT_DIFF
from classification_version x inner join classification_element y
on x.id_project=y.ID_PROJECT inner join email e
on x.id_project=e.ID_PROJECT_AMENDMENT
where
y.ID_PROJECT=project.id and y.ID_COMPANY=company.id
and e.SEND_DATE>x.OPTENTION_DATE group by e.id,e.SEND_DATE
order by e.SEND_DATE ASC)
This is only a part of a query that I have. I need to return min(datediff) because I need the corresponding name value only. But it throws an error that Operand should contain 1 column(s). I cannot use inner queries for the select statement as project.id and company.id will not be available to me then. IS there any way to solve this?

I modified your SQL check it once.
SELECT CONCAT(q1.NAME,' ',DT_DIFF) FROM
(SELECT x.NAME,MIN(DATEDIFF(e.SEND_DATE, x.OPTENTION_DATE))
AS DT_DIFF
FROM classification_version x INNER JOIN classification_element y
ON x.id_project=y.ID_PROJECT INNER JOIN email e
ON x.id_project=e.ID_PROJECT_AMENDMENT
WHERE
y.ID_PROJECT=project.id AND y.ID_COMPANY=company.id
AND e.SEND_DATE>x.OPTENTION_DATE GROUP BY e.id,e.SEND_DATE
ORDER BY e.SEND_DATE ASC) AS q1
Thank you.

Related

SQL Complex update query filter distinct values only

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.

Show id even result is empty?

I have the SQL command:
SELECT
vinculo.id,
data start,
count(*) title
from
atendimento_regulacao
join vinculo on vinculo.id = atendimento_regulacao.vinculo_id
where data = '2019-07-02'
group by vinculo.usuario_id, atendimento_regulacao.data
The result is empty because not exists none record on where data = '2019-07-02'
How to show the id like below?
id | start | title
1 | |
You can use a CROSS JOIN to generate the rows and LEFT JOIN to bring in the results:
select v.id, d.dte as start, count(ar.vinculo_id) as num_title
from (select '2019-07-02' as dte) d cross join
vinculo v left join
atendimento_regulacao ar
on v.id = ar.vinculo_id and ar.data = d.dte
group by v.id, d.dte;
If you really want to aggregate by v.usuario_id, then include it in both the select and group by.
Notes:
The structure of the query easily extends to multiple dates.
The GROUP BY uses the same columns in the SELECT.
Table aliases make the query easier to write and to read.
Qualify all column references in a query that has more than one table reference.
The COUNT() uses a column from ar so it can return 0.
For the specific case of a single date, you can use conditional aggregation:
select v.id, '2019-07-02' as start,
count(ar.vinculo_id) as num_title
from vinculo v left join
atendimento_regulacao ar
on v.id = ar.vinculo_id and ar.data = '2019-07-02'
group by v.id;
Use RIGHT JOIN, and convert your count to the one below, otherwise it shows zero whenever didn't find to count anything.
SELECT v.id, a.data start,
case when count(*) is null then null end title
FROM atendimento_regulacao a
RIGHT JOIN vinculo v
ON v.id = a.vinculo_id
AND a.data = '2019-07-02'
GROUP BY v.usuario_id, a.data;
Demo

Group Concat from a select statement

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.

Using SQL variables with INNER JOINS

Im trying to use a variable to count the number of rows i have for a specific id, if i use it without inner joins it works perfectly, otherwise no, here is the section without joins
select
cd.basis_point bpt,
cd.created,
#version:=#version+1 version
from tbl_class_det cd, (select #version:=1) v
where (cd.class_uuid='{$row['uuid']}')
and (cd.created>(
select
created
from tbl_class_det
where (class_uuid=cd.class_uuid)
order by created asc
limit 1
))
order by cd.created asc
the section with joins that gives an error:
select c.name,
fd.value bpt,
fd.created,
#version:=#version+1 version
from tbl_fee_det fd, (select #version:=1) v
INNER JOIN tbl_fee f ON f.uuid = fd.fee_uuid
INNER JOIN tbl_class c ON c.uuid = f.class_uuid
where (fd.created>(
select
created
from tbl_class_det
where (fee_uuid=f.uuid)
order by created asc
limit 1
))
order by fd.created asc;
You are using a combination of explicit and implicit joins. You should not mix the JOIN syntax with the comma syntax. If you need to you this then use a subquery similar to this:
select name,
value bpt,
created,
#version:=#version+1 version
from
(
select c.name,
fd.value,
fd.created,
f.uuid
FROM tbl_fee_det fd
INNER JOIN tbl_fee f
ON f.uuid = fd.fee_uuid
INNER JOIN tbl_class c
ON c.uuid = f.class_uuid
) f, (select #version:=1) v
where (created>(select created
from tbl_class_det
where (fee_uuid=f.uuid)
order by created asc
limit 1))
order by created asc;

mysql subquery returns more than 1 row

I have the following query :
(select xyz.* from
(select xt.image, p.*, pc.categoryid, c.category,
(select value from xcart_extra_field_values
where efv.productid=p.productid and efv.fieldid = 2) as Type,
(select value from xcart_extra_field_values
where efv.productid=p.productid and efv.fieldid = 1) as Zone
FROM xcart_products p
inner join xcart_products_categories pc
on p.productid=pc.productid
inner join xcart_categories c
on pc.categoryid=c.categoryid
inner join xcart_extra_field_values efv
on p.productid=efv.productid
inner join xcart_images_T xt
on p.productid=xt.id) xyz
where categoryid='1' and Type='2' and Zone='1'
group by productid)
But when I execute this query in phpmyadmin it displays a error messgae :
#1242 - Subquery returns more than 1 row
Whats wrong in the query.Please help. Thanks in advance.
I think (part of) the problem is that you are re-using an alias in a wrong location.
You should one use an alias once, and don't mix them for different instances of the same table.
(select xyz.* from
(select xt.image, p.*, pc.categoryid, c.category,
(select value from xcart_extra_field_values efv2
where efv2.productid=p.productid and efv2.fieldid = 2) as Type,
(select value from xcart_extra_field_values efv3
where efv3.productid=p.productid and efv3.fieldid = 1) as Zone
FROM xcart_products p
inner join xcart_products_categories pc
on p.productid=pc.productid
inner join xcart_categories c
on pc.categoryid=c.categoryid
inner join xcart_extra_field_values efv1
on p.productid=efv1.productid
inner join xcart_images_T xt
on p.productid=xt.id) xyz
where categoryid='1' and Type='2' and Zone='1'
group by productid)
So use a unique alias efvx for each xcart_extra_field_values table instance.
Execute each subquery manually in phpmyadmin and see which one is returning more than one row and you have your answer. Another option is to add a limit of 1 to each subquery to make sure only one row is returned. Of course it is better to look for the bug and solve it.