Getting 1 Value to 1 column - mysql

Good day.
I need to output look like this, is it possible this output.
I have my script:
myoutput is this
SELECT q_type,q_title,qcategory_question
FROM `survey_question` as sq LEFT JOIN
(SELECT id,qid,qcategory_question
FROM survey_category_question
) scq ON sq.id = scq.qid
Thanks in advance.

Your query is fine. You should handle the formatting in the application. Now, I am going to make a different suggestion, which is to bring all the categories on a single row using group by:
SELECT sq.q_type, sq.q_title, GROUP_CONCAT(scq.qcategory_question)
FROM survey_question sq LEFT JOIN
survey_category_question scq
ON sq.id = scq.qid
GROUP BY sq.q_type, sq.q_title;
Notes:
Qualify all column names in the query, especially when you have more than one table reference.
The subquery is unnecessary and probably detrimental in MySQL (most databases would ignore it, but MySQL may materialize it).
The resulting categories will be in a comma-delimited list for output.

Although i will not suggest you to do this in query as you could do that in php easily, you can try this..
SET #row_number = 0;
SELECT q_type, CASE
WHEN A.mxnum = AA.num
THEN q_title
ELSE ' '
END AS q_title, qcategory_question
FROM (
SELECT q_type, q_title, qcategory_question, (#row_number: = #row_number + 1)
AS num FROM `survey_question` AS sq
LEFT JOIN (
SELECT id, qid, qcategory_question
FROM survey_category_question
) AA
LEFT JOIN (
SELECT q_title, max(num) AS mxnum
FROM (
SELECT q_type, q_title, qcategory_question, (#row_number: = #row_number + 1) AS num
FROM `survey_question` AS sq
LEFT JOIN (
SELECT id, qid, qcategory_question
FROM survey_category_question
) scq
ON sq.id = scq.qid
)
GROUP BY q_title
) A
ON num = mxnum
);
hope this helps...

Related

Joining a second table and selecting the first entry

I have been having some troubles getting my head around achieving the below.
I have an 'applications' table and a 'application_logs' table. I am attempting to select all the applications where the 'type' is equal to 'test' and then join the 'application_logs' table and retrieve only the first log entry for the application.
One of the queries I tried and understood most was: (whilst this didn't fail it looked like an endless loop and completed the query.
SELECT applications.id FROM applications JOIN application_logs ON application_logs.application_id =
(
SELECT application_logs.id FROM application_logs
WHERE application_logs.application_id = applications.id
ORDER BY id DESC
LIMIT 1
)
WHERE type = 'test';
There were some other queries (using CROSS APPLY/distinct) I attempted but they didn't make sense to me and didn't look like they were trying to achieve the same thing. I appreciate all the help :)
There are many ways to achieve this in standard SQL. A lateral join (CROSS APPLY) is the first to come to mind, but MySQL doesn't support it. Another would be FETCH FIRST ROWS WITH TIES to get all latest application logs, but MySQL doesn't support it (and its counterpart LIMIT doesn't have a ties clause either). If you are only interested in the application ID alone (as shown in your query) one could even combine this with an INTERSECT operation, but MySQL doesn't support it.
After all you want to find out the maximum log ID per application ID. As of MySQL 8 you can do this on-the-fly:
select *
from applications a
left join
(
select
application_logs.*,
max(id) over (partition by application_id) as max_application_id
from application_logs
) al on al.application_id = a.id and al.application_id = al.max_application_id
where a.type = 'test';
In earlier vesions you would do this in separate steps. One way would be this:
select *
from applications a
left join application_logs al
on al.application_id = alm.application_id
and (al.application_id, al.id) in
(
select application_id, max(id)
from application_logs
group by application_id
)
where a.type = 'test';
Another is your own query, where you only got confused with the IDs:
SELECT *
FROM applications a
JOIN application_logs al ON al.id =
(
SELECT almax.id
FROM application_logs almax
WHERE almax.application_id = a.id
ORDER BY almax.id DESC
LIMIT 1
)
WHERE a.type = 'test';
try this
SELECT
a.*, c.*
FROM
applications a
INNER JOIN (
SELECT
al.application_id AS application_id,
MAX(al.id) AS al_id
FROM
application_logs al
GROUP BY
al.application_id
) c ON a.id = c.application_id
WHERE
a.type = 'test';
To get the first entry from application_logs table with respect to application_id. You need to use Row_Number Over (partition by order by ).
SELECT *
FROM applications A
LEFT JOIN (
SELECT Id AS applications.id
FROM (
SELECT ROW_NUMBER() OVER (Partition By applications.id ORDER BY application_logs.id) as R, application_logs.id, applications.id
FROM application_logs
) AS S
WHERE R = 1
) AS L ON L.applications.id = A.applications.id
Try this -
SELECT a.id, ay.*
FROM applications AS a
INNER JOIN (
SELECT al.application_id, min(al.id) as Min_Id
FROM application_logs AS al
GROUP BY al.application_id
) AS ax ON ax.application_id = a.id
INNER JOIN application_logs AS ay ON ay.id = ax.id
WHERE a.type = 'test';
Your query suggests that "first" means the largest id. (Colloquially, I would expect "first" to mean the smallest id or earliest chronologically.)
I usually recommend a correlated subquery for the filtering. It is worth testing if this is faster than other methods:
select . . .
from applications a join
application_logs al
on al.application_id = a.id
where a.type = 'test' and
al.id = (select max(al2.id)
from application_logs al2
where al2.application_id = al.application_id
);
The optimal indexes for performance are:
application(type, id)
application_logs(application_id, id)

Selection of the maximum deleted_data from duplicate rows

Table structure:
It is not possible to select records with the maximum delete date, which are grouped by one code, with the condition that they are all deleted. If the records have the same code, but have different delete statuses, then you do not need to select these records.
In this example, you select records with id = 3, id = 4.
SELECT * FROM analyzes_test WHERE code IN (SELECT code FROM analyzes_test GROUP BY code HAVING count(code)>1) AND deleted = (max deleted_date)
But I do not know how to substitute the longest possible date for deletion.
Please tell me who has more experience with sql.
Try the following simple query-:
select code,max(deleted_date) MAX_DeletedDate
from analyzes_test
group by code
having count(deleted_date)>1
you could use an inner join on max date group by code
select *
FROM analyzes_test a
inner join (
select code, max(deleted_date) max_date
FROM analyzes_test
group by code
) t on t.max_date = a.deleted_date and t.code = a.code
or if you don't want thw result for code with only a rows a could use
select *
FROM analyzes_test a
inner join (
select code, max(deleted_date) max_date
FROM analyzes_test
group by code
having count(*)>1
) t on t.max_date = a.deleted_date and t.code = a.code
TRY THIS: GROUP BY and HAVING will help to retrieve the max date of each code and use it as a subquery to retrieve all the information for the table as below:
SELECT ant.*
FROM analyzes_test ant
INNER JOIN (SELECT code, MAX(deleted_date) max_date
FROM analyzes_test
WHERE deleted_date IS NOT NULL
GROUP BY code
HAVING COUNT(deleted_date) > 1) t ON t.code = ant.code
AND t.max_date = ant.deleted_date

MySQL linked table get the last row insered with table.value = X

I current have a table project(id) and a table project_step (id, project,step(integer)).
1 project is linked to 1 or many project_step.
I want to get a list of project where the last entered project_step (project_step.id DESC) has a step = X.
I need to do this in a sub query but i don't know how to write it.
This query will return all column from both tables. The purpose of the extra subquery is to separately get the latest ID for every project on table project_step.
SELECT a.*, b.*
FROM project a
INNER JOIN project_step b
ON a.ID = b.project
INNER JOIN
(
SELECT project, MAX(ID) ID
FROM project_step
GROUP BY project
) c ON b.project = c.project AND
b.ID = c.ID
WHERE b.step = ?
Try something like this.
SELECT project.* from project_step
JOIN project ON project.id = project_step.project
GROUP BY project
HAVING SUBSTRING_INDEX(GROUP_CONCAT(step ORDER BY step DESC SEPARATOR ' '), ' ', 1) = X

Multiple Selects in Single Query

I'm hoping someone fluent in MySQL will be able to assist me with this. I'm trying to do a select on a select on a select, but the query doesn't seem to want to complete. Any help would be greatly appreciated.
SELECT
product as pid,
leg_name as name,
dimensions as dims
FROM
pmaint
WHERE
product in (
SELECT product
FROM qb_export_items_attributes
WHERE attribute_name = 'Z'
AND product in (
SELECT product
FROM pmainT
WHERE type_ID = (
SELECT ID
FROM type
WHERE SOFTCARTCATEGORY = 'End Table Legs'
)
)
AND attribute_value <= 3.5
)
Try to use INNER JOINs instead of IN subqueries
UPD: I've edited this query according you comment. the first JOIN subquery output all product where both attributes exists and true.
SELECT
pmaint.product as pid,
pmaint.leg_name as name,
pmaint.dimensions as dims
FROM
pmaint
JOIN (select product from qb_export_items_attributes
where ((attribute_name = 'Z') and (attribute_value <= 3.5))
OR
((attribute_name = 'top_square') and (attribute_value >= 4))
GROUP BY product HAVING COUNT(*)=2
)
t1 on (pmaint.product=t1.product )
JOIN type on (pmaint.type_ID=type.ID)
WHERE
type.SOFTCARTCATEGORY = 'End Table Legs'

Mysql: same query, different results

EDIT:
Sorry about unreadable query, I was under deadline. I managed to solve problem by breaking this query into two smaller ones, and doing some business logic in Java. Still want to know why this query can random times return two different results.
So, it randomly returns once all expected results, other time just half. I noticed that when I write it join per join, and execute after each join, in the end it returns all expected results. So am wandering if there's some kind of MySql memory or other limitation that it doesn't take whole tables in joins. Also read on undeterministic queries but not sure what to tell.
Please help, ask if needs clarification, and thank you in advance.
RESET QUERY CACHE;
SET SQL_BIG_SELECTS=1;
set #displayvideoaction_id = 2302;
set #ticSessionId = 3851;
select richtext.id,richtextcross.name,richtextcross.updates_demo_field,richtext.content from
(
select listitemcross.id,name,updates_demo_field,listitem.text_id from
(
select id,name, updates_demo_field, items_id from
(
SELECT id, name, answertype_id, updates_demo_field,
#student:=CASE WHEN #class <> updates_demo_field THEN 0 ELSE #student+1 END AS rn,
#class:=updates_demo_field AS clset FROM
(SELECT #student:= -1) s,
(SELECT #class:= '-1') c,
(
select id, name, answertype_id, updates_demo_field from
(
select manytomany.questions_id from
(
select questiongroup_id from
(
select questiongroup_id from `ticnotes`.`scriptaction` where ticsession_id=#ticSessionId and questiongroup_id is not null
) scriptaction
inner join
(
select * from `ticnotes`.`questiongroup`
) questiongroup on scriptaction.questiongroup_id=questiongroup.id
) scriptgroup
inner join
(
select * from `ticnotes`.`questiongroup_question`
) manytomany on scriptgroup.questiongroup_id=manytomany.questiongroup_id
) questionrelation
inner join
(
select * from `ticnotes`.`question`
) questiontable on questionrelation.questions_id=questiontable.id
where updates_demo_field = 'DEMO1' or updates_demo_field = 'DEMO2'
order by updates_demo_field, id desc
) t
having rn=0
) firstrowofgroup
inner join
(
select * from `ticnotes`.`multipleoptionstype_listitem`
) selectlistanswers on firstrowofgroup.answertype_id=selectlistanswers.multipleoptionstype_id
) listitemcross
inner join
(
select * from `ticnotes`.`listitem`
) listitem on listitemcross.items_id=listitem.id
) richtextcross
inner join
(
select * from `ticnotes`.`richtext`
) richtext on richtextcross.text_id=richtext.id;
My first impression is - don't use short cuts to describe your tables. I am lost at which td3 is where ,then td6, tdx3... I guess you might be lost as well.
If you name your aliases more sensibly there will be less chance to get something wrong and mix 6 with 8 or whatever.
Just a sugestion :)
There is no limitation on mySQL so my bet would be on human error - somewhere there join logic fails.