Get result from joined tables - mysql

I have 2 tables:
Table 1:
| jobid | jobname |
| 1 | job a |
| 2 | job b |
Table 2:
| id | jobid | statusid | statusdate | desc |
| 1 | 1 | 100 | 2019.04.25 10:00:00 | first |
| 2 | 2 | 100 | 2019.04.25 11:00:00 | first |
| 3 | 2 | 100 | 2019.04.25 12:00:00 | second |
Jobs in table2 can have more then one same "statusid", but different "statusdate" and "desc"
I need to get jobs list with the last "statusid" = 100 like this :
| 1 | job a | 1 | 1 | 100 | 2019.04.25 10:00:00 | first |
| 2 | job b | 3 | 2 | 100 | 2019.04.25 12:00:00 | second |
SELECT * FROM table1
INNER JOIN table2 ON table1.id = table2.jobid
GROUP BY table1.id
This query return wrong result like:
| 1 | job a | 1 | 1 | | 100 | 2019.04.25 10:00:00 | first |
| 2 | job b | 3 | 2 | 2 | 100 | 2019.04.25 11:00:00 | first |

You should be able to accomplish that by doing something like this:
Table
drop table if exists table1;
create table table1 (jobid int, jobname char(10));
insert into table1 values (1, 'job a'), (2, 'job b');
drop table if exists table2;
create table table2 (
id int,
jobid int,
statusid int,
statusdate timestamp,
`desc` char(10)
);
insert into table2 values
(1,1,100,'2019.04.25 10:00:00','first')
,(2,2,100,'2019.04.25 11:00:00','first')
,(3,2,100,'2019.04.25 12:00:00','second');
Query
select
t1.*,
t2.*
from table1 t1
inner join (
select jobid, max(statusdate) as maxstatusdate
from table2
group by jobid
) tn on t1.jobid = tn.jobid
inner join table2 t2 on tn.jobid = t2.jobid and tn.maxstatusdate = t2.statusdate;
Results
jobid jobname id jobid statusid statusdate desc
1 job a 1 1 100 25.04.2019 10:00:00 first
2 job b 3 2 100 25.04.2019 12:00:00 second
Explanation
For each job ID, find the maximum status date
Join that to table1 to get information from table1. Common field is jobid
Join their result to table2 that has all the remaining information you want. Common fields are jobid and statusdate. Since we aliased max status date to a different name, make sure we are using the correct name in the join
Example: https://rextester.com/HRSWZ89705

DROP TABLE IF EXISTS table1;
CREATE TABLE table1
(jobid INT NOT NULL PRIMARY KEY
,jobname VARCHAR(12) UNIQUE
);
INSERT INTO table1 VALUES
(1,'job a'),
(2,'job b'),
(3,'job c');
DROP TABLE IF EXISTS table2;
CREATE TABLE table2
(id SERIAL PRIMARY KEY
,jobid INT NOT NULL
,statusid INT NOT NULL
,statusdate DATETIME NOT NULL
,description VARCHAR(12) NOT NULL
);
INSERT INTO table2 VALUES
(1,1,100,'2019-04-25 10:00:00','first'),
(2,2,100,'2019-04-25 11:00:00','first'),
(3,2,100,'2019-04-25 12:00:00','second');
SELECT a.*
, b.id x_id
, b.statusid
, b.statusdate
, b.description
FROM table1 a
LEFT
JOIN
( SELECT x.*
FROM table2 x
JOIN
( SELECT MAX(id) id
FROM table2
WHERE statusid = 100
GROUP
BY jobid
) y
ON y.id = x.id
) b
ON b.jobid = a.jobid
;
+-------+---------+------+----------+---------------------+-------------+
| jobid | jobname | x_id | statusid | statusdate | description |
+-------+---------+------+----------+---------------------+-------------+
| 1 | job a | 1 | 100 | 2019-04-25 10:00:00 | first |
| 2 | job b | 3 | 100 | 2019-04-25 12:00:00 | second |
| 3 | job c | NULL | NULL | NULL | NULL |
+-------+---------+------+----------+---------------------+-------------+

SELECT
t1.*,t2.* FROM
(SELECT
MAX(id) as id
FROM
table2
WHERE statusid = 100
GROUP BY jobid) AS f
JOIN table2 t2
ON t2.id = f.id
JOIN table1 t1
ON t2.jobid = t1.jobid
The sub query select finds the last id for a row with statusid 100, then it joins the actual table based on this id.
You can reorder this as you wish using the correct joins.

Related

Multiple times values are coming in mysql

I have two tables
tbl1 and tbl2
tbl1 table contains 5 columns name id(pk), email , address ,pid(INDEX),status(ENUM Y,N)
tbl2 table contains 3 columns id(pk) ,pid(INDEX),domain
When i am running this query
SELECT *
FROM tbl1 as l
LEFT JOIN tbl2 as m on l.pid=m.pid
WHERE l.status='Y';
It is giving multiple records . Please note we are making join in pid both pid are not primary key. Please help to get only unique values from both table.
enter image description here
You seem to want to join on the basis of relative position in the tables.A way to do this is row_number simulation using variables.
drop table if exists t1,t2;
create table t1(id int, email varchar(5),address varchar(10),pid int,status varchar(1));
create table t2(id int, pid int, domain varchar(5));
insert into t1 values (1,'aa#aa', 'aaaaa',428,'Y'), (2,'bb#bb', 'bbbbb',428,'n'),(3,'cc#cc', 'ccccc',428,'Y') ;
insert into t2 values (1,428,'mmm'),(2,428,'zzz');
select t1.*,t2.*
from
(
select t1.*,
if(t1.pid <> #pid1, #bn1:=#bn1+1,#bn1:=#bn1) BlockNo1,
if(t1.id <> #id1, #rn1:=#rn1+1, #rn1:=1) rowno1,
#pid1:=t1.pid pid1,
#id1:=t1.id p1
from t1
cross join (select #bn1:=0,#rn1:=0, #pid1:=0 ,#id1:=0) r
where status = 'y'
order by t1.pid,t1.id
) t1
join
(
select t2.id t2id,t2.pid t2pid, t2.domain t2domain,
if(t2.pid <> #pid2, #bn2:=#bn2+1,#bn2:=#bn2) BlockNo2,
if(t2.id <> #id2, #rn2:=#rn2+1, #rn2:=1) rowno2,
#pid2:=t2.pid pid2,
#id2:=t2.id p2
from t2
cross join (select #bn2:=0,#rn2:=0, #pid2:=0 ,#id2:=0) r
order by t2.pid,t2.id
) t2 on (t1.blockno1 = t2.blockno2) and (t1.rowno1 = t2.rowno2)
+------+-------+---------+------+--------+----------+--------+------+------+------+-------+----------+----------+--------+------+------+
| id | email | address | pid | status | BlockNo1 | rowno1 | pid1 | p1 | t2id | t2pid | t2domain | BlockNo2 | rowno2 | pid2 | p2 |
+------+-------+---------+------+--------+----------+--------+------+------+------+-------+----------+----------+--------+------+------+
| 1 | aa#aa | aaaaa | 428 | Y | 1 | 1 | 428 | 1 | 1 | 428 | mmm | 1 | 1 | 428 | 1 |
| 3 | cc#cc | ccccc | 428 | Y | 1 | 2 | 428 | 3 | 2 | 428 | zzz | 1 | 2 | 428 | 2 |
+------+-------+---------+------+--------+----------+--------+------+------+------+-------+----------+----------+--------+------+------+
2 rows in set (0.04 sec)

Group by priority

I have this
+---------+--------+-------+
| article | name |status |
+---------+--------+-------+
| 0001 | A | enable|
| 0002 | A | temp |
| 0003 | B | enable|
| 0004 | C | enable|
+---------+--------+-------+
I want to select all from this table 'product' but I want to group by name and if there is a status temp I want to ignore the enable status and display only the product with the temp status
This result after query will be :
+---------+--------+-------+
| article | name |status |
+---------+--------+-------+
| 0002 | A | temp |
| 0003 | B | enable|
| 0004 | C | enable|
+---------+--------+-------+
Could you help me to build this query ?
If find at least one temp in group, show it. Else show enable
select article, name, if(sum(status='temp'), 'temp', 'enable')
from thetable
group by name
To get article corresponding to temp status, use such query
select * from table1
where status = 'temp'
union
select * from table1
where name not in (select distinct name from table1 where status = 'temp' )
Try this, hope help for you;)
SQL Fiddle
MySQL 5.6 Schema:
CREATE TABLE table1
(`article` int, `name` varchar(1), `status` varchar(6))
;
INSERT INTO table1
(`article`, `name`, `status`)
VALUES
(0001, 'A', 'enable'),
(0002, 'A', 'temp'),
(0003, 'B', 'enable'),
(0004, 'C', 'enable')
;
Query 1:
select t1.*
from table1 t1
inner join (
select count(distinct status) cnt, name, group_concat(status) as names from table1 group by name
) t2 on t1.name = t2.name
and (t2.cnt = 1 or (find_in_set('temp', names) > 0 and t1.status = 'temp'))
group by t1.name, t1.status
Results:
| article | name | status |
|---------|------|--------|
| 2 | A | temp |
| 3 | B | enable |
| 4 | C | enable |

SQL: Join 2 tables and get only one result per condition from the first table

I have the following tables:
Auction-table
Id | Title | Description
------------------------
1 | Test1 | DescriptionForTest1
2 | Test2 | DescriptionForTest2
3 | Test3 | DescriptionForTest3
and
Bids-Table
AuctionId | UserId | Bidding
----------------------------
1 | 2 | 10
1 | 32 | 24
1 | 2 | 30
1 | 46 | 50
2 | 13 | 5
2 | 20 | 10
and so on...
Now I want a output, similar to this
AuctionId | Title | Description | UserId
----------------------------------------
1 | Test1 | Desc... | 46
2 | Test2 | Desc... | 20
I need one row per auction with the UserId with the highest Bidding.
I know that I could do this with 2 SQL-Statements. First getting all auctions and second with MAX(Bidding). But I need this in one statement and I'm stucking to get a working SQL-Statement.
Could anyone help me please?
I'm using MySQL as DBMS.
DROP TABLE IF EXISTS auction;
CREATE TABLE auction
(auction_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,Title VARCHAR(12) NOT NULL UNIQUE
,Description VARCHAR(30) NOT NULL
);
INSERT INTO auction VALUES
(1 ,'Test1','DescriptionForTest1'),
(2 ,'Test2','DescriptionForTest2'),
(3 ,'Test3','DescriptionForTest3');
DROP TABLE IF EXISTS bids;
CREATE TABLE bids
(auction_id INT NOT NULL
,user_id INT NOT NULL
,bid INT NOT NULL
,PRIMARY KEY (auction_id,user_id,bid)
);
INSERT INTO bids VALUES
(1 ,2 ,10),
(1 ,32 ,24),
(1 ,2 ,30),
(1 ,46 ,50),
(2 ,13 ,5),
(2 ,20 ,10);
SELECT a.*
, b.user_id
, b.bid
FROM auction a
JOIN bids b
ON b.auction_id = a.auction_id
JOIN
( SELECT auction_id, MAX(bid) max_bid FROM bids GROUP BY auction_id) c
ON c.auction_id = b.auction_id
AND c.max_bid = b.bid;
+------------+-------+---------------------+---------+-----+
| auction_id | Title | Description | user_id | bid |
+------------+-------+---------------------+---------+-----+
| 1 | Test1 | DescriptionForTest1 | 46 | 50 |
| 2 | Test2 | DescriptionForTest2 | 20 | 10 |
+------------+-------+---------------------+---------+-----+
Strawberry's answer is one way. Here is a second way. Try them both and see which one is faster on your setup. Indexes and table sizes will make a big difference.
SELECT High_Bid.AuctionId, A.Title, A.Description, High_Bid.UserID FROM
(
SELECT * FROM
(
SELECT * FROM bids_table
ORDER BY AuctionId, Bidding DESC
) AS B1
GROUP BY AuctionId
) AS High_Bid
JOIN
auction_table AS A
ON High_Bid.AuctionId=A.Id
Query:
SQLFIDDLEExample
SELECT t.*
FROM (
SELECT a.Id AS AuctionId,
a.Title,
a.Description,
(SELECT b.UserId
FROM Bids b
WHERE b.AuctionId = a.Id
ORDER BY b.Bidding DESC
LIMIT 1) as UserId
FROM Auction a) t
WHERE T.UserID is not null
Result:
| AUCTIONID | TITLE | DESCRIPTION | USERID |
----------------------------------------------------
| 1 | Test1 | DescriptionForTest1 | 46 |
| 2 | Test2 | DescriptionForTest2 | 20 |
It works with this sql:
select ID, Title, Description, UserId from Auction a
right join Bids b on a.ID = b.AuctionId
right join (select AuctionId, max(Bidding) as Bidding from Bids group by AuctionId) c on b.AuctionId = c.AuctionId and b.Bidding = c.Bidding;
Fiddle is here: fiddle
Result with a third user:
ID TITLE DESCRIPTION USERID
1 Test1 DescriptionForTest1 46
2 Test2 DescriptionForTest2 20
3 Test3 DescriptionForTest3 23
SELECT MAX(BINDING),A.AUCTION_ID,A.DESCRIPTION,A.TITLE,B.USER_ID
FROM AUCTION_TABLE A,BIDS_TABLE B
WHERE A.AUCTION_ID=B.AUCTION_ID
OR TRY WITH JOINS
SELECT MAX(BINDING),A.AUCTION_ID,A.DESCRIPTION,A.TITLE,B.USER_ID
FROM AUCTION_TABLE A
INNER JOIN BIDS_TABLE B ON A.AUCTION_ID=B.AUCTION_ID

Query MySQL Group by and Having

I am creating an application for my school and I am in trouble constructing the right query.
I have 2 tables,table1 and table2.
table1
---------------------------------------------------------
| StudentID | SubjectID | Present | Type |
---------------------------------------------------------
| 2 | 3 | yes | 1 |
| 2 | 2 | yes | 2 |
| 3 | 1 | no | 3 |
---------------------------------------------------------
table2
---------------------------------------------------------
| SubjectID | SubjectName | Number1 | Number2 |
---------------------------------------------------------
| 1 | Name1 | 6 | 4 |
| 2 | Name2 | 4 | 8 |
| 3 | Name3 | 5 | 2 |
---------------------------------------------------------
SubjectID in table1 is foreign key references table2.
I want to build a query sql that gives me the StudentID`s from table1
that didnt miss any Type 3 subject (i.e no row like this
---------------------------------------------------------
| StudentID | SubjectID | Present | Type |
---------------------------------------------------------
| 3 | 1 | no | 3 |
---------------------------------------------------------
And have completed 75 percent of type 1 (i.e
I find it like this
SELECT t1.StudentID,t1.SubjectID ,t1.Type,t2.Number1 as num
FROM table1 as t1,table2 as t2
WHERE t1.Present=yes and t2.SubjectID=t1.SubjectID
GROUP BY StudentID,SubjectID
HAVING COUNT(*)/num >= 75/100
But I cant combine the two things together.
You can combine queries by giving them aliases and joining as subqueries...
SELECT finisher.StudentID FROM
(
SELECT DISTINCT StudentID
FROM table1 t1
JOIN table2 t2 ON t2.SubjectID = t1.SubjectID
WHERE t1.Present = 'yes' AND t1.Type1 = 1
GROUP BY t1.StudentID, t2.SubjectID
HAVING COUNT(*) / t2.Number2 >= 0.75
) finisher
JOIN
(
SELECT DISTINCT t1.StudentID
FROM table1 t1
LEFT JOIN
(
SELECT DISTINCT StudentID
FROM table1
WHERE Type = 3 AND Present = 'no'
) missed ON missed.StudentID = t1.StudentID
WHERE t1.Type = 3
AND missed.StudentID IS NULL
) notmissed ON finisher.StudentID = notmissed.StudentID
"StudentID`s from table1 that didnt miss any Type 3"... I assume here you don't want to include students without any type 3 rows.
Seems like this is done and duste, but how about...
SELECT x.*
FROM
( SELECT t1.StudentID
, t1.SubjectID
, t1.Type
, t2.Number1 num
FROM table1 t1
JOIN table2 t2
ON t2.SubjectID=t1.SubjectID
WHERE t1.Present='yes'
GROUP
BY t1.StudentID
, t1.SubjectID
HAVING COUNT(*)/num >= 0.75
) x
LEFT
JOIN table1 y
ON y.student_id = x.student_id
AND y.subject_id = x.subject_id
AND y.type = 3
AND y.present = 'no'
WHERE y.student_id IS NULL;

SQL Query selecting row with unique record in a table's column?

I'm having a problem with my query by selecting the rows with unique id in one column.
Here's my db looks like:
Table 1
user_id | user_name | user_email
1 john ex0#email
2 nathel ex1#email
3 bob ex2#email
Table 2
subs_id | user_id | prod_id
1 1 1
2 1 2
3 2 1
4 3 1
5 3 3
Table 3
prod_id | prod_name
1 Platinum
2 Gold
3 Steel
What I need to do is to select the user row from Table 1 join with Table 2 & 3 that has a unique record in Table 2 user_id column based on their subscription.
Example. I want to select the user subscribing only in platinum, so the output must be looks like this :
user_id | user_name | user_email | subs_id | user_id | prod_id | prod_id | prod_name
2 nathel ex1#email 3 2 1 1 Platinum
SELECT * from users u inner join subscription s on u.user_id = s.user_id
inner join products p on p.prod_id = s.prod_id
WHERE s.user_id IN (SELECT user_id from subscription GROUP by user_id HAVING count(user_id) = 1) AND s.prod_id = 1
The last piece of the puzzle has been omitted as an exercise for the reader...
DROP TABLE IF EXISTS users;
CREATE TABLE users
(user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,user_name VARCHAR(20) NOT NULL UNIQUE
,user_email VARCHAR(12) NOT NULL
);
INSERT INTO users VALUES
(1 ,'john','ex0#email'),
(2 ,'nathel','ex1#email'),
(3 ,'bob','ex2#email');
DROP TABLE IF EXISTS product_user;
CREATE TABLE product_user
(product_id INT NOT NULL
,user_id INT NOT NULL
,PRIMARY KEY (product_id,user_id)
);
INSERT INTO product_user VALUES
(1, 1),(2 ,1),(1 ,2),(1,3),(3,3);
DROP TABLE IF EXISTS products;
CREATE TABLE products
(product_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,product_name VARCHAR(12) NOT NULL UNIQUE);
INSERT INTO products VALUES (1 ,'Platinum'),(2,'Gold'),(3,'Steel');
SELECT *
FROM product_user x
LEFT
JOIN product_user y
ON y.user_id = x.user_id
AND y.product_id <> x.product_id
WHERE x.product_id =1;
+------------+---------+------------+---------+
| product_id | user_id | product_id | user_id |
+------------+---------+------------+---------+
| 1 | 1 | 2 | 1 |
| 1 | 2 | NULL | NULL |
| 1 | 3 | 3 | 3 |
+------------+---------+------------+---------+
SELECT *
FROM product_user x
LEFT
JOIN product_user y
ON y.user_id = x.user_id
AND y.product_id <> x.product_id
JOIN users u
ON u.user_id = x.user_id
JOIN products p
ON p.product_id = x.product_id
WHERE p.product_name = 'Platinum';
+------------+---------+------------+---------+---------+-----------+------------+------------+--------------+
| product_id | user_id | product_id | user_id | user_id | user_name | user_email | product_id | product_name |
+------------+---------+------------+---------+---------+-----------+------------+------------+--------------+
| 1 | 1 | 2 | 1 | 1 | john | ex0#email | 1 | Platinum |
| 1 | 2 | NULL | NULL | 2 | nathel | ex1#email | 1 | Platinum |
| 1 | 3 | 3 | 3 | 3 | bob | ex2#email | 1 | Platinum |
+------------+---------+------------+---------+---------+-----------+------------+------------+--------------+
Hope so you are looking for this :
SELECT * FROM table1 as t1
inner join table2 as t2 on t1.user_id = t2.user_id
inner join table3 as t3 on t2.prod_id = t3.prod_id
where t3.prod_name = 'Platinum';
I think you can use DISTINCT to fetch unique recodes from database in query
SELECT DISTINCT
t1.`user_id` ,t1.`user_name`,t1.`user_email`,t2.`subs_id`,t2.`user_id`,t2.`prod_id`,t3.`prod_id` ,t3.`prod_name`
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.`user_id`=t2.`user_id`
INNER JOIN Table3 t3
ON t2.`prod_id`=t3.`prod_id`
WHERE
t1.`user_id`='2'
Hope this will be helpful to you
Please! try below code snip
select t1.user_id ,t1.user_name,t1.user_email,
t2.subs_id,t2.user_id , t2.prod_id ,
t3.prod_id , t3.prod_name
from table2 t2 inner join table1 t1 on t2.user_id=t1.user_id
inner join table3 t3 on t3.prod_id=t2.prod_id and t2.prod_id =1