poll_opts table for storing options and poll_voted for storing vote result, pid stands for poll id(unique) and oid stands for option id(unique for individual poll only)
poll_voted [Primary Key: pid.oid.emp]
+-----+-----+-------+
| pid | oid | emp |
+-----+-----+-------+
poll_opts [Primary Key: pid.oid]
+-----+-----+---------+
| pid | oid | opt |
+-----+-----+---------+
pid & oid type: int , opt type: text
If you need the "not existent" results as well you need a left outer join preserves all results from poll_opts even if no match in poll_votes is found.
MySql 5.7 Join Syntax
Query:
select opt, count(vo.oid)
from poll_opts po
left outer join poll_voted vo on vo.oid = po.oid and po.pid=vo.pid
where po.pid = 3 -- 3
group by opt
Output:
opt count(vo.oid)
Chrome 0
Firefox 0
IE 0
MS Edge 0
Opera 1
Testdata:
CREATE TABLE poll_voted (`pid` int, `oid` int, `emp` int);
INSERT INTO poll_voted (`pid`, `oid`, `emp`)
VALUES
(1, 0, 1989),
(1, 2, 1989),
(1, 4, 1989),
(1, 6, 1989),
(3, 2, 1989)
;
CREATE TABLE poll_opts (`pid` int, `oid` int, `opt` varchar(15));
INSERT INTO poll_opts (`pid`, `oid`, `opt`)
VALUES
(1, 0, 'WinXP'),
(1, 2, 'wIN7'),
(1, 4, 'wIN 10'),
(1, 6, 'Ubuntu'),
(3, 0, 'IE'),
(3, 1, 'MS Edge'),
(3, 2, 'Opera'),
(3, 3, 'Chrome'),
(3, 4, 'Firefox')
;
Related
My sql looks like:
create table ad(
ad_id int,
ad_name varchar(10)
);
insert into ad(ad_id, ad_name) values
(1,'ad1'),
(2,'ad2'),
(3,'ad3');
create table ad_insight(
id int,
ad_id int,
date date,
clicks int
);
insert into ad_insight(id, ad_id, date, clicks) values
(1, 1, '2021-04-25', 1),
(2, 1, '2021-04-24', 4),
(3, 1, '2021-04-23', 2),
(4, 2, '2021-04-25', 6),
(5, 2, '2021-03-03', 7);
create table product(
product_id int,
product_name varchar(10)
);
insert into product(product_id, product_name) values
(1,'prod1'),
(2,'prod2'),
(3,'prod3'),
(4,'prod4'),
(5,'prod5');
create table product_insight(
id int,
product_id int,
sale int,
date date
);
insert into product_insight(id, product_id, sale, date) values
(1, 1, 12, '2021-04-25'),
(2, 1, 11, '2021-04-24'),
(3, 1, 13, '2021-04-23'),
(4, 1, 14, '2021-04-22'),
(5, 1, 17, '2021-04-21'),
(6, 1, 15, '2021-04-20'),
(7, 1, 13, '2021-04-19'),
(8, 2, 19, '2021-04-25');
create table ads_products(
ad_id int,
product_id int
);
insert into ads_products (ad_id, product_id) values
(1, 1),
(1, 2),
(2, 3),
(2, 4),
(1, 3);
Here you have fiddle
A quick explanation of schema:
I have ads:
each ad has insights, which tell us when a certain ad was active.
each ad has products(many2many - ads_products table). Each product has product_insight which tells us how many sales that product generated on a certain day.
And now I want to get the following table which will sum up clicks from ad_insight table and sum up product_sale from product_insight in 2021-04-23 to 2021-04-25 inclusive.
+----------+--------+--------------+--------------+
| ad_name | clicks | product_sale | products |
+----------+--------+--------------+--------------+
| ad1 | 7 | 55 | prod1, prod2 |
| ad2 | 6 | 0 | prod3, prod4 |
| ad3 | 0 | 36 | prod1 |
+----------+--------+--------------+--------------+
What I have tried?
select ad_name, SUM(ad_insight.clicks) as clicks
from ad
left join ad_insight on ad.ad_id = ad_insight.ad_id
where ad_insight.date >= '2021-04-23' and ad_insight.date <= '2021-04-25'
group by ad.ad_id;
But I do not know how to select product_sale table and products separated by a comma?
I would like to update Table Lease from Table History
CREATE TABLE Lease
(`LeaseID` int, `Name` varchar(3), `Users` varchar(15), `WhoSignID` int, `NoteDate` date)
;
INSERT INTO Lease
(`LeaseID`, `Name`, `Users`, `WhoSignID`, `NoteDate`)
VALUES
(1, 'AAA', '1000,1001', NULL, NULL),
(2, 'BBB', '1002', NULL, NULL),
(3, 'CCC', '1003,1004', NULL, NULL),
(4, 'DDD', '1005,1006, 1007', NULL, NULL)
;
CREATE TABLE History
(`HistoryID` int, `LeaseID` int, `User` int, `SignDate` date)
;
INSERT INTO History
(`HistoryID`, `LeaseID`, `User`, `SignDate`)
VALUES
(1, 1, 1000, '2020-01-05'),
(2, 1, 1001, '2020-01-04'),
(3, 1, 1001, '2020-01-02'),
(4, 1, 1000, '2020-01-03'),
(6, 2, 1002, '2020-05-01'),
(7, 2, 1002, '2020-05-03')
;
I looking of a Mysql Update to update Table Lease :
NoteDate and WhoSignID based on SignDate and User
where Minimum of SignDate of User
Table Lease After Update
LeaseID | Name | Users | WhoSignID | NoteDate
1 | AAA | 1000,1001 | 1001 | 2020-01-02
2 | BBB | 1002 | 1002 | 2020-05-01
...
I appreciate any assist
Your Lease table has a serious design problem, because it is storing users as a CSV list. Instead, you should have each user value on a separate record. That being said, it appears that the CSV user list is immaterial to your current problem, which only required finding the earliest date for each lease. If so, then a simple update join should suffice:
UPDATE Lease l
INNER JOIN
(
SELECT h1.LeaseID, h1.User, h2.MinSignDate
FROM History h1
INNER JOIN
(
SELECT LeaseID, MIN(SignDate) AS MinSignDate
FROM History
GROUP BY LeaseID
) h2
ON h2.LeaseID = h1.LeaseID AND
h2.MinSignDate = h1.SignDate
) h
ON h.LeaseID = l.LeaseID
SET
WhoSignID = h.User,
NoteDate = h.MinSignDate;
I have two tables. I need to join these two tables and retrieve latest status from execution table. How can I retrieve?
My schema and data:
CREATE TABLE test
(`id` serial primary key, `ref_id` int, `ref_name` varchar(7))
;
INSERT INTO test
(`id`, `ref_id`, `ref_name`)
VALUES
(1, 1, 'trial'),
(2, 3, 'test'),
(3, 7, 'testing')
;
CREATE TABLE execution
(`id` serial primary key, `ref_id` int, `status` varchar(11))
;
INSERT INTO execution
(`id`, `ref_id`, `status`)
VALUES
(1, 1, 'Completed'),
(2, 2, 'Completed'),
(3, 1, 'Completed'),
(4, 3, 'In progress'),
(5, 3, 'To do'),
(6, 2, 'In progress'),
(7, 1, 'Completed'),
(7, 1, 'To do')
;
Expected result is here below.
ref_id | ref_name | status |
3 | testing | In progress |
2 | test | To do |
1 | trial | To do |
I have tried with below query:
SELECT
ref_id,
ref_name,
status
FROM
test
JOIN execution ON test.ref_id = execution.ref_id
GROUP BY `ref_id`
ORDER BY `ref_id` DESC;
This query retrieves the status, but the retrieved status is not a latest one. How can retrieve the latest status by joining these two tables.
you can use below query
select T2.ref_id,T2.ref_name,OE.status from
(
select t1.ref_id,t1.ref_name,e.id from test t1 inner join
(select max(id) as id,ref_id from execution group by ref_id) as e
on
t1.ref_id=e.ref_id
) as T2
inner join execution OE on T2.id=OE.id
https://www.db-fiddle.com/f/rvnm8APX27dmW9a84JkCsS/1
It seems you have given in-correct data as an example as ref_id 7 not found in
execution table. However this might help you
SELECT b.ref_id,
b.ref_name,
a.status
FROM execution a
JOIN (SELECT MAX(id) id ,ref_id
FROM execution
GROUP BY ref_id) a1
USING(id,ref_id)
JOIN test b ON a.ref_id = b.ref_id ORDER BY ref_id DESC;
I have a difficult task to build up an array retrieved from a table similar to the one below:
table_a
id | scenario_id | entity_id
1 1;2;3;4;5 1;3
2 4;5;8;10 2;3
3 1;5;8;11 1;2;4;
4 3;5;8;9 4;5;
Now, if one user selects from one entity_id, let's say 3, the SQL query should return something similiar to:
scenario_id
1;2;3;4;5;8;10
Or, if he selects 5, the returned array should look like:
scenario_id
3;5;8;9
Could that be done using only SQL statements?
For SQL Server you can use this to get desired output:
DECLARE #xml xml, #entity_id int = 3
--Here I generate data similar to yours
;WITH cte AS (
SELECT *
FROM (VALUES
(1, '1;2;3;4;5', '1;3'),
(2, '4;5;8;10', '2;3'),
(3, '1;5;8;11', '1;2;4;'),
(4, '3;5;8;9', '4;5;')
) as t(id, scenario_id, [entity_id])
)
--create xml
SELECT #xml = (
SELECT CAST('<i id="'+ CAST(id as nvarchar(10)) +'"><s>' + REPLACE(scenario_id,';','</s><s>') + '</s><e>' + REPLACE([entity_id],';','</e><e>') + '</e></i>' as xml)
FROM cte
FOR XML PATH('')
)
--Normalizing the table and getting result
SELECT STUFF((
SELECT ';' + CAST(scenario_id as nvarchar(10))
FROM (
SELECT DISTINCT t.v.value('.','int') as scenario_id
FROM #xml.nodes('/i/s') as t(v)
INNER JOIN #xml.nodes('/i/e') as s(r)
ON t.v.value('../#id','int') = s.r.value('../#id','int')
WHERE s.r.value('.','int') = #entity_id
) as p
FOR XML PATH('')),1,1,'') as scenario_id
Output for entity_id = 3:
scenario_id
1;2;3;4;5;8;10
For entity_id = 5
scenario_id
3;5;8;9
you can use something like this to find a id in the scenario_id, but its always a FULL TABLE scan.
SELECT *
FROM table_a
WHERE
FIND_IN_SET('3', REPLACE(scenario_id,';',',')) > 0;
Simple. NORMALISE your schema... At it's crudest, that might be as follows...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL
,scenario_id INT NOT NULL
,entity_id INT NOT NULL
,PRIMARY KEY (id,scenario_id,entity_id)
);
INSERT INTO my_table VALUES
(1, 1,1),
(1, 1,3),
(1, 2,1),
(1, 2,3),
(1, 3,1),
(1, 3,3),
(1, 4,1),
(1, 4,3),
(1, 5,1),
(1, 5,3),
(2, 4,2),
(2, 4,3),
(2, 5,2),
(2, 5,3),
(2, 8,2),
(2, 8,3),
(2,10,2),
(2,10,3),
(3, 1,1),
(3, 1,2),
(3, 1,4),
(3, 5,1),
(3, 5,2),
(3, 5,4),
(3, 8,1),
(3, 8,2),
(3, 8,4),
(3,11,1),
(3,11,2),
(3,11,4),
(4, 3,4),
(4, 3,5),
(4, 5,4),
(4, 5,5),
(4, 8,4),
(4, 8,5),
(4, 9,4),
(4, 9,5);
SELECT DISTINCT scenario_id FROM my_table WHERE entity_id = 3 ORDER BY scenario_id;
+-------------+
| scenario_id |
+-------------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 8 |
| 10 |
+-------------+
split the scenario_id by ';' and copy to temporary table to use that for your query use instr and substring functions
this link may help you but you need a loop function to call your procedure as the ';' is repeated
I have 3 tables in my database:
Student:
id
name
Student_Course:
student_id
course_id
Course:
id
grade
And I want to list all the students and the results of whether they have pass all of the course they have chosen . Assuming that grade <= 'C' is pass.
I tried sql like:
SELECT s.*,
IF('C'>=ALL(SELECT c.grade FROM from Course c WHERE c.id=sc.course_id),1,0) as isPass
FROM Student s LEFT JOIN Student_Course sc on sc.student_id=s.id
This sql works, but if now I want a column 'isGood' which means all the grade='A', do I need to execute the subquery again? How can I get both 'isGood' and 'isPass' by executing subquery only once?
I believe the grade would be better served in the junction table. Using that, I have created a scenario that might help you solve your question:
Scenario
create table student (id int, fullname varchar(50));
insert into student values (1, 'john'), (2, 'mary'), (3, 'matt'), (4, 'donald');
create table course (id int, coursename varchar(50));
insert into course values (1, 'math'), (2, 'science'), (3, 'business');
create table student_course (student_id int, course_id int, grade char(1));
insert into student_course values
(1, 1, 'C'), (1, 2, 'C'), (1, 3, 'C'),
(2, 1, 'A'), (2, 2, 'A'), (2, 3, 'A'),
(3, 1, 'A'), (3, 2, 'C'), (3, 3, 'C'),
(4, 1, 'A'), (4, 2, 'C'), (4, 3, 'F');
Query
select s.*, case when all_a_grades.student_id is not null then 'GOOD' else 'MEH' end as grades
from student s
left join (
-- find students who got A in all classes
select student_id, count(distinct ca.id) as aclasses, count(distinct sc.course_id) as allclasses
from student_course sc
left join (select id, 'A' as agrade from course) ca
on ca.id = sc.course_id and ca.agrade = sc.grade
group by student_id
having aclasses = allclasses
) all_a_grades on all_a_grades.student_id = s.id
where not exists (
-- let's make sure we filter OUT students who have failed
-- at least one course
select 1
from (
-- find students who have failed at least one course
select distinct student_id
from student_course
where grade not in ('A', 'B', 'C')
) t where t.student_id = s.id
)
Result
| id | fullname | grades |
| 1 | john | MEH |
| 2 | mary | GOOD |
| 3 | matt | MEH |