Using IF with JOIN in SELECT mysql - mysql

I am trying to get data and join the table with other IF match certain attribute in base table. Following code may explain what I am trying to do:
SELECT * FROM Base_Table
LEFT JOIN
IF(Base_Table.Class = "A",
Type ON Type.Id = Base_Table.Type_Id,
Box_Type ON Box_Type.Id = Base_Table.Type_Id)
WHERE Base_Table.Id = 4;

I had same question as your but I found solution by using UNION; IF is for select filed not for table. I will suggest you to use UNION like in example below:
SELECT * FROM Base_Table
LEFT JOIN Type ON Type.Id = Base_Table.Type_Id
WHERE Base_Table.Id = 4
UNION
SELECT * FROM Base_Table
LEFT JOIN Box_Type ON Box_Type.Id = Base_Table.Type_Id
WHERE Base_Table.Id = 4;
Hope this will work for you!

Related

"Duplicate column name" error that shouldn't exist

I'm trying to migrate a database from sqlite to mariaDB ( which I never worked with ) and I can't seem to get past this problem!
When I try to run this, I always get
"#1060 - Duplicate column name 'id_document'"
Here's the query:
SELECT
a.id_document AS id_document,
id_user_associatedDoc,
id_user_creator,
stage,
title,
goldStandardAnnotationManual,
count(content) AS answer_count
FROM
(SELECT *
FROM Document join DocumentProject
ON Document.id_document = DocumentProject.id_document
WHERE DocumentProject.id_project = 2) a
LEFT JOIN
(SELECT *
FROM Annotation
WHERE Annotation.id_project = 2) b
ON a.id_document = b.id_document
GROUP BY a.id_document;
I don't understand why I should be getting this error! Can you help?
This first subquery syntax returns two id_document column:
(SELECT *
FROM Document
join DocumentProject
ON Document.id_document = DocumentProject.id_document
WHERE DocumentProject.id_project = 2) a
A quick way to fix this:
SELECT
a.id_doc /*Change this column as following*/ AS id_document,
id_user_associatedDoc,
id_user_creator,
stage,
title,
goldStandardAnnotationManual,
count(content) AS answer_count
FROM
(SELECT *, Document.id_document as "id_doc" /*define the first id_document column as a different name*/
FROM Document
join DocumentProject
ON Document.id_document = DocumentProject.id_document
WHERE DocumentProject.id_project = 2) a
LEFT JOIN
(SELECT *
FROM Annotation
WHERE Annotation.id_project = 2) b
ON a.id_document = b.id_document
GROUP BY a.id_document;
You can also pre-define which column you want to return inside the subquery as well. Example:
(SELECT Document.id_document, Document.column_2, Document.column_3
FROM Document
join DocumentProject
ON Document.id_document = DocumentProject.id_document
WHERE DocumentProject.id_project = 2) a
That way, your outer query should select the a.id_document according to what you have pre-define inside the subquery and no need to change anything from the outer query.

Order query output according to 'is in table/ is not in table'

I have the following Database Design:
Database Design
I want to get all Information from table 'info' where the id IS NOT in table 'archived'. To do so I wrote:
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
WHERE
i.branch_id = 4 AND i.user_id = 7 a.info_id IS NULL ORDER BY i.info_date_from ASC
This works as expected.
The next challenge is to only show information that are also included in the 'published' table. To get this done I have expanded my previous query to :
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
RIGHT JOIN
traffic_info_publised p ON (i.info_id = p.info_id)
WHERE
i.branch_id = 4 AND a.info_id AND i.user_id = 7 IS NULL ORDER BY i.info_date_from ASC
This does also work as expected.
The final challenge is to Order this result according to table 'read'. Information´s id that are NOT in table 'read' should be ordered ASC. But even if its id does not appear in table 'read' they should not be excluded from the query output. BUT the primary ORDER should be
i.info_date_from ASC
I hope this is understandable, my English is not the best :) If not, please comment and I will do my best to make it understandable. Hope some can help!
I´ve tried to create a SQLFiddle, but I wasn´t able to create a runnable example, sorry for that.
UPADTE:
Using the approach from #Dylan Su
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
INNER JOIN
traffic_info_publised p ON (i.info_id = p.info_id)
WHERE
i.branch_id = 4 AND a.info_id AND i.user_id = 7 IS NULL
ORDER BY
CASE WHEN NOT EXISTS(SELECT 1 FROM read WHERE i.info_id = read.info_id)
THEN i.info_date_from END ASC;
the goal is nearer then it ever was :)
Sample Data output
Both entries marked with a red "X" are in table read. Therefore id 3 should be last the, in the middle 1 and 2 at the top.
So the last thing to archive is to do the correct order of table read. I´ve tried sth like:
(SELECT 1 FROM traffic_info_read WHERE i.info_id = traffic_info_read.info_id ORDER BY traffic_info_read.info_id DESC)
But that didn´t had any influnce.
Try this:
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
INNER JOIN
traffic_info_publised p ON (i.info_id = p.info_id)
WHERE
i.branch_id = 4 AND a.info_id AND i.user_id = 7 IS NULL
ORDER BY
EXISTS(SELECT 1 FROM read WHERE i.info_id = read.info_id) ASC,
i.info_date_from ASC;
The Answer of #Dylan Su is absolutely correct and I won´t unmark it as accepted.
However, based on the Information I gained from the conversation I have created another solution, that doesn´t make use of sub query.
I heard that using just JOIN´s will result in better performance, I don´t know if it´s correct and I don´t have that much test data currently to find out, but here is the solution using no sub query.
SELECT *
FROM traffic_info i
LEFT JOIN
traffic_info_archived a ON (i.info_id = a.info_id)
INNER JOIN
traffic_info_published p ON (i.info_id = p.info_id)
LEFT JOIN
traffic_info_read r ON (i.info_id = r.info_id)
WHERE
i.branch_id = 4 AND a.info_id IS NULL ORDER BY r.info_id IS NULL DESC, i.info_date_from ASC
;

Mysql row query to codeigniter query

I have the following Mysql query. Running as needed.
SELECT
t_doc.*, t_user.IDA, t_data.IDA
FROM
( SELECT DISTINCT IDau FROM t_doc ) IDau_list
LEFT OUTER JOIN
(
SELECT
IDd ,IDau
FROM
t_doc
WHERE
doc_type = 'doc'
GROUP BY IDau
)
doc_images ON doc_images.IDau = IDau_list.IDau
LEFT OUTER JOIN
(
SELECT
IDd ,IDau
FROM
t_auto_doc
WHERE
doc_type = 'jpg'
GROUP BY IDau
)
jpg_images ON jpg_images.IDau = IDau_list.IDau
LEFT OUTER JOIN
t_doc ON t_doc.IDdoc = COALESCE(jpg_images.IDd, doc_images.IDd)
LEFT OUTER JOIN
t_user ON t_user.IDau = t_doc.IDau
LEFT OUTER JOIN
t_data ON t_user.IDA = t_data.IDA
But, What I must bring this query to codeigniter Model, in which I have to adapt the query, as example like this...
$this->db->select('u.IDau, a.*');
$this->db->from('t_user u');
$this->db->join('t_doc d', 'd.IDau=u.IDau', 'left');
And ...More.....Here......
But, I got it difficult. Is some one out there might change it Please..
Thanks in advance
As #NEVERMIND Suggest I have accomplish the task using...
$query = $this->db->query("My QUERY WITH A BIT OF CHANGE");
Yes, I should make some change to get the exact Data as i needed.
Thanks for all of your comments and ideas.

How do I create the SQL for this relationship?

How do I get the survey sections by product id using the best method?
Also if this relationship has a name please provide it in your answer.
As requested my attempt:
SELECT *
FROM survey_sections
JOIN survey_sections_map ON survey_sections_map.survey_section_id = survey_sections.id
JOIN product_tags_map
WHERE product_tags_map.product_id = 2
second attempt...
SELECT *
FROM survey_sections
JOIN survey_sections_map ON survey_sections_map.survey_section_id = survey_sections.id
JOIN product_tags_map ON product_tags_map.product_tag_id = survey_sections_map.product_tag_id
WHERE product_tags_map.product_id = 2
I think We can use nested select queries as well, don't know this is the best way or not but you should try it ones.
SELECT sur.name
FROM survey_sections AS sur
INNER JOIN survey_sections_map AS surmap ON sur.id = surmap.survey_section_id
WHERE surmap.product_tag_id IN (SELECT product_tag_id FROM product_tags_map WHERE product_id = 2)

MySQL get rest of values

Using this query
SELECT DISTINCT(job_primary.id) AS id
FROM `job_primary`
LEFT JOIN `job_skill` ON `job_skill`.`job_id` = `job_primary`.`id`
LEFT JOIN `job_facts` ON `job_facts`.`job_id` = `job_primary`.`id`
LEFT JOIN `job_location` ON `job_location`.`job_id` = `job_primary`.`id`
LEFT JOIN `job_people` ON `job_people`.`job_id` = `job_primary`.`id`
LEFT JOIN `job_sec` ON `job_sec`.`job_id` = `job_primary`.`id`
AND job_sec.exp_start_date > UNIX_TIMESTAMP()
INNER JOIN `user_skills` ON `user_skills`.`skill_id` = `job_skill`.`skill_id`
AND user_skills.user_id = 1
WHERE job_primary.posted_by != 1
I am getting only the id value. But I want to get the rest of the values with distinct id. Don't think about rest of the codes. The problem is here, if I use:
select *, job_primary.id as id
to select code then I get all data. But it is not distinct. So if I used
SELECT *, distinct(job_primary.id) as id
or
SELECT distinct(job_primary.id), * as id
but it is showing errors.
I think your confussion is what to query itself, nixon1333. What do you want to ask to the database? If you want just one row per id, group'em by with SELECT * FROM ... GROUP BY job_primary.id