I tried to re-write a SQL query using subquery to one using common table expression (CTE). The former is as below
select accounting_id, object_code, 'active', name
from master_data md
where md.id in (
select MIN(md1.id)
from master_data md1
where md1.original_type = 'tpl'
group by md1.object_code
);
The one below failed with
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near 'distinct_object_code_id' at line 9
with distinct_object_code_id(id) as (
select MIN(md1.id)
from master_data md1
where md1.original_type = 'tpl'
group by md1.object_code
)
select md.accounting_id, md.object_code, 'active', md.name
from master_data md
where md.id in distinct_object_code_id;
This one also failed
with distinct_object_code_id as (
select MIN(md1.id)
from master_data md1
where md1.original_type = 'tpl'
group by md1.object_code
)
select md.accounting_id, md.object_code, 'active', md.name
from master_data md
join distinct_object_code_id using(id)
;
whereas this one below works (by explicitly specify the column_list)
with distinct_object_code_id(id) as (
select MIN(md1.id)
from master_data md1
where md1.original_type = 'tpl'
group by md1.object_code
)
select md.accounting_id, md.object_code, 'active', md.name
from master_data md
join distinct_object_code_id using(id)
;
I tried another one but it also failed (using subquery inside CTE)
with distinct_object_code_id as (
select accounting_id, object_code, 'active', name
from master_data md
where md.id in (
select MIN(md1.id)
from master_data md1
where md1.original_type = 'tpl'
group by md1.object_code
)
select * from distinct_object_code_id;
The MYSQL database version is 8.0.29-0ubuntu0.20.04.3.
what did I do wrong when using CTE?
EDIT:
I add a third part, in which I inserted the data from those queries above into another table tpl_transferred_debtor like below
with distinct_object_code_id as (
select MIN(id) as id
from master_data
where original_type = 'tpl'
group by object_code
),
tmp_tpl_table as (
select md.accounting_id, md.object_code, 'active', md.name
from master_data md
join distinct_object_code_id using(id)
)
insert into tpl_transferred_debtor(debtor_id, tpl_code, status, description)
select * from tmp_tpl_table;
This one failed with
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insert into tpl_transferred_debtor(debtor_id, tpl_code, status, description) sel' at line 12
I tried to write a simple one to check if the second CTE tmp_tpl_table and it is ok
with distinct_object_code_id as (
select MIN(id) as id
from master_data
where original_type = 'tpl'
group by object_code
),
tmp_tpl_table as (
select md.accounting_id, md.object_code, 'active', md.name
from master_data md
join distinct_object_code_id using(id)
)
select * from tmp_tpl_table;
Your first query fails because you cannot use IN to reference cte you have to join or the correct syntax for IN ie in (select..from cte)
Your second query fails because you didn't alias MIN(md1.id)
Your third query works because you referenced MIN(md1.id) by providing (ID)
Personally I prefer join..on over join..using
Related
I want to use data of view in WHERE clause. But getting an error:
create view post_with_answers AS
SELECT DISTINCT postid
FROM (SELECT postid FROM `qa_posts` WHERE `type` = 'Q') AS q1
INNER JOIN (SELECT parentid FROM `qa_posts` WHERE `type` = 'A') AS q2 ON q1.postid = q2.parentid
select count(*)
from qa_posts
where parentid not in post_with_answers
On the last row I am getting this error:
SQL Error [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'post_with_answers' at line 3
How to fix that?
Just like you would use a table:
select count(*)
from qa_posts
where parentid not in (select pwa.postid from post_with_answers pwa);
I would caution you from using not in with a subquery. No rows are returned if even one value from the subquery is NULL. For this reason, I recommend NOT EXISTS:
select count(*)
from qa_posts p
where not exists (select 1
from post_with_answers pwa
where p.parentid = pwa.postid
);
In addition, your view definition is a bit over complicated. You don't need subqueries:
create view post_with_answers AS
SELECT DISTINCT pq.postid
FROM qa_posts pq JOIN
qa_posts pa
ON pq.postid = pa.parentid
WHERE pq.type = 'Q' AND pa.type = 'A';
Then, the DISTINCT just adds overhead, so EXISTS is better:
create view post_with_answers AS
SELECT DISTINCT pq.postid
FROM qa_posts pq
WHERE EXISTS (SELECT 1
FROM qa_posts pa
WHERE pq.postid = pa.parentid AND
pa.type = 'A'
)
WHERE pq.type = 'Q';
I have the following query:
select a.clei, a.partNumber,
(
SELECT count(*) FROM
( SELECT * from search_upload_data s where a.clei is not null AND a.clei = s.clei
UNION
SELECT * from search_upload_data s where a.partNumber is not null AND a.partNumber = s.partNumber
) as t1
) as total
from api_analytics_data a
It is throwing the error:
Error Code: 1054. Unknown column 'a.clei' in 'where clause'
I guess MySQL won't allow a join reference in the inner SQL, but I'm not sure how to get around this.
I need the count from search_upload_data, See SQL Fiddle here: http://sqlfiddle.com/#!9/172ac/2
<=========================================================================>
ADDITIONAL NOTE
I need to figure out how to do this with a UNION. The OR conditions in everyone's answers work on a small scale, but bog down on the actual DB with a lot of data.
Here is the explain (for Rajat's answer):
TRY THIS: Simple join with OR and GROUP BY
SELECT a.clei,
a.partNumber,
COUNT(1) tot
FROM api_analytics_data a
LEFT JOIN search_upload_data s ON (a.clei = s.clei OR a.partNumber = s.partNumber)
AND (a.clei is not null OR a.partNumber is not null)
GROUP BY a.clei, a.partNumber
OUTPUT: http://sqlfiddle.com/#!9/94e556/1
try this
select a.clei, a.partNumber,
( SELECT COUNT(1) As Total
from search_upload_data s
where ( a.clei is not null AND a.clei = s.clei )
OR (a.partNumber is not null AND a.partNumber = s.PartNumber)
) as t1
from api_analytics_data a
This corresponds with your desired output anyway. Just using a regular OR to select either clei or partnumber.
select a.clei, a.partNumber,
(
SELECT count(*) FROM search_upload_data s WHERE
(a.clei is not null AND a.clei = s.clei) OR
(a.partNumber is not null AND a.partNumber = s.partNumber)
) as Total
from api_analytics_data a
select a.clei, a.partNumber,
(
SELECT count(s.id) FROM search_upload_data s where (a.clei is not null AND a.clei = s.clei) OR (a.partNumber is not null AND a.partNumber = s.partNumber)
) as Total
from api_analytics_data a
try now
Is there a limit of subquerys where the referencing outer column is working on?
I tried this query:
SELECT
`userouter`.`id` AS `user_id`
FROM
`users` AS `userouter`
WHERE
123456 = (
SELECT
SUM(`tmp`.`sum`) AS `sum_total`
FROM
(
SELECT
SUM(`invoiceposition`.`number` * `invoiceposition`.`amount`) AS `sum`
FROM
`invoices` AS `invoice` INNER JOIN
`invoicepositions` AS `invoiceposition` ON
`invoice`.`id` = `invoiceposition`.`invoice`
WHERE
`invoice`.`user` = `userouter`.`id`
GROUP BY
`invoice`.`id`
) AS `tmp`
)
GROUP BY
`userouter`.`id`
And i get Error Code: 1054. Unknown column 'userouter.id' in 'where clause'
How can i reference the userouter.id in the sub-sub query?
As it seems in a normal way not possible to resolve the problem (double nested subquery reference to outer query), i now solved the problem by creating a mysql function with the user id as parameter.
hope this will help other searchers
Remove the double nesting.
SELECT
`userouter`.`id` AS `user_id`
FROM
`users` AS `userouter`
LEFT JOIN (
SELECT
`invoice`.`user` as `user_id`, SUM(`invoiceposition`.`number` * `invoiceposition`.`amount`) AS `sum`
FROM
`invoices` AS `invoice` INNER JOIN
`invoicepositions` AS `invoiceposition` ON
`invoice`.`id` = `invoiceposition`.`invoice`
WHERE
`invoice`.`user` = `userouter`.`id`
GROUP BY
`invoice`.`id`
) AS `tmp`
ON `tmp`.`user_id` = `userouter`.`id`
WHERE
123456 = `userouter`.`id`
GROUP BY
`userouter`.`id`
i have 3 tables.
tenant
tenant_id : int
category_id : int
category
category_id : int
category_name : varchar(50)
history
tenant_id : int
bulan_tahun : varchar(8)
counter : int
i want to join all of this table using this code:
SELECT a.tenant_id, a.category_name
FROM (
(tenant INNER JOIN category ON tenant.category_id = category.category_id) AS a
INNER JOIN (
SELECT tenant_id, counter FROM history WHERE
bulan_tahun = DATE_FORMAT(CURDATE(), '%m_%Y')
) AS b
on a.tenant_id = b.tenant_id
)
but this code produce an error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'a INNER JOIN ( SELECT tenant_id, counter FROM history WHERE bulan_tahun ' at line 3
if i separate the sub select, it works perfectly
for the first select:
SELECT tenant_id, category_name
FROM
(tenant INNER JOIN category ON tenant.category_id = category.category_id)
and the second select:
SELECT tenant_id, counter FROM history WHERE
bulan_tahun = DATE_FORMAT(CURDATE(), '%m_%Y')
but if i join this together, the error occured
can anyone help me?
Problem lies here..
(tenant INNER JOIN category ON tenant.category_id = category.category_id)
Try restructuring your entire query like this
SELECT a.tenant_id, c.category_name
FROM
tenant t
INNER JOIN
category c
ON ( t.category_id = c.category_id )
INNER JOIN
history h
ON ( t.tenant_id = h.tenant_id )
WHERE
h.bulan_tahun = DATE_FORMAT(CURDATE(), '%m_%Y')
This is the original SQL statement to retrieve course data:
SELECT
`courses`.`id` AS `id`,
`courses`.`title` AS `title`,
`courses`.`description` AS `description`,
MATCH (coursedata.title) AGAINST ('Salsa') * 5 + MATCH (coursedata.description) AGAINST ('Salsa') * 2 AS `relevance`,
GROUP_CONCAT(trainers.name SEPARATOR '|||') AS `trainers`
FROM `courses`
INNER JOIN `coursedata` ON `courses`.`id` = `coursedata`.`id`
INNER JOIN `courses_trainers` ON `courses`.`id` = `courses_trainers`.`course_id`
INNER JOIN `trainers` ON `trainer_id` = `trainers`.`id`
GROUP BY `courses`.`id`
HAVING `relevance` >= '3'
Since it uses the MySQL Extensions to GROUP BY and cannot be executed, if the sql_mode is set to ONLY_FULL_GROUP_BY, I had to make it standard SQL conform:
SELECT * FROM (
SELECT
`courses`.`id` AS `id`,
`courses`.`title` AS `title`,
`courses`.`description` AS `description`,
MATCH (coursedata.title) AGAINST ('Salsa') * 5 + MATCH (coursedata.description) AGAINST ('Salsa') * 2 AS `relevance`
-- , GROUP_CONCAT(trainers.name SEPARATOR '|||') AS `trainers`
FROM `courses`
INNER JOIN `coursedata` ON `courses`.`id` = `coursedata`.`id`
LEFT JOIN `courses_trainers` ON `courses`.`id` = `courses_trainers`.`course_id`
LEFT JOIN `trainers` ON `trainer_id` = `trainers`.`id`
) AS subselect
WHERE `relevance` >= '3'
This one wors fine, but I cannot use the GROUP_CONCAT function (in order to concatenate multiple trainer fields to one field/string) anymore.
Error Code: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_CONCAT(trainers.name SEPARATOR '|||') AS `trainers`
FROM `courses`
INNER' at line 7
Is there another way to use the GROUP_CONCAT functionality?