I have a schema as follows;
CREATE TABLE `vehicle` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`vehiclelicence` varchar(50) DEFAULT NULL,
`userid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`companyid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
);
insert into vehicle (vehiclelicence, userid) values ('PB1234', 1);
insert into vehicle (vehiclelicence, userid) values ('AB0987', 2);
insert into vehicle (vehiclelicence, userid) values ('UI7654', 3);
insert into vehicle (vehiclelicence, userid) values ('DV8888', 4);
insert into vehicle (vehiclelicence, userid) values ('PB1234', 2);
insert into vehicle (vehiclelicence, userid) values ('UI7654', 1);
insert into user (username, companyid) values ('Bob', 1);
insert into user (username, companyid) values ('Tim', 2);
insert into user (username, companyid) values ('Jim', 3);
insert into user (username, companyid) values ('Fred', 4);
insert into company (name) values ('Company 1');
insert into company (name) values ('Company 2');
insert into company (name) values ('Company 3');
insert into company (name) values ('Company 4');
Users add vehiclelicences all the time.
How can I return all vehiclelicences listed by more than one company and which company listed it?
This is the sql I have so far, but it lists all the records.
SELECT *
FROM vehicle v1
join user u on u.id = v1.userid
join company c on c.id = u.companyid
WHERE EXISTS
(
SELECT 1
FROM vehicle v2
WHERE v1.vehiclelicence = v1.vehiclelicence and v2.userid != v1.userid
LIMIT 1, 1
)
order by v1.vehiclelicence
;
I have created a Fiddle
This is the desired output
+----------------+--------+----------+-----------+-------------+
| vehiclelicence | userid | username | companyid | companyname |
+----------------+--------+----------+-----------+-------------+
| PB1234 | 1 | Bob | 1 | Company 1 |
| PB1234 | 2 | Tim | 2 | Company 2 |
| UI7654 | 3 | Jim | 3 | Company 3 |
| UI7654 | 1 | Bob | 1 | Company 1 |
+----------------+--------+----------+-----------+-------------+
Thank you.
WHERE v1.vehiclelicence = v1.vehiclelicence - a typo here..and remove the limit and it works.
SELECT *
FROM vehicle v1
join user u on u.id = v1.userid
join company c on c.id = u.companyid
WHERE EXISTS
(
SELECT 1
FROM vehicle v2
WHERE v1.vehiclelicence = v2.vehiclelicence and v2.userid != v1.userid
#LIMIT 1, 1
)
order by v1.vehiclelicence
;
OR start the offset from 0
SELECT *
FROM vehicle v1
join user u on u.id = v1.userid
join company c on c.id = u.companyid
WHERE EXISTS
(
SELECT 1
FROM vehicle v2
WHERE v1.vehiclelicence = v2.vehiclelicence and v2.userid != v1.userid
LIMIT 0, 1
)
order by v1.vehiclelicence
;
either way
+----+----------------+--------+----+----------+-----------+----+-----------+
| id | vehiclelicence | userid | id | username | companyid | id | name |
+----+----------------+--------+----+----------+-----------+----+-----------+
| 1 | PB1234 | 1 | 1 | Bob | 1 | 1 | Company 1 |
| 5 | PB1234 | 2 | 2 | Tim | 2 | 2 | Company 2 |
| 6 | UI7654 | 1 | 1 | Bob | 1 | 1 | Company 1 |
| 3 | UI7654 | 3 | 3 | Jim | 3 | 3 | Company 3 |
+----+----------------+--------+----+----------+-----------+----+-----------+
4 rows in set (0.001 sec)
Related
Taking into account the tables provided below, I want to be able to count the occurrences of how many Events a User still hasn't provided availability yet.
Table users
| name | id |
|---------|----|
| John | 1 |
| Francis | 2 |
| Peter | 3 |
| Mike | 4 |
Table events
| id | name |
|----|---------|
| 1 | Event 1 |
| 2 | Event 2 |
Table availability
| answer | event_id | user_id |
|--------|----------|---------|
| yes | 1 | 1 |
| yes | 2 | 1 |
| no | 1 | 2 |
| maybe | 2 | 4 |
The expected answer would then be:
Expected answer:
| user_id | count |
|---------|-------|
| 1 | 0 |
| 2 | 1 |
| 3 | 2 |
| 4 | 1 |
I have been able to do a query for how many events each member has responded, but looking for how many hasn't responded.
DBFiddle: https://www.db-fiddle.com/f/mwv4F1wYZ9UxB56L9mMjFQ/1
SQL:
create table events (
id int auto_increment primary key,
name varchar(100) null
);
create table users (
name varchar(100) null,
id int auto_increment primary key
);
create table availability (
answer text null,
event_id int null,
user_id int not null,
constraint availability_events_id_fk
foreign key (event_id) references events (id),
constraint availability_users_id_fk
foreign key (user_id) references users (id)
);
INSERT INTO events (id, name) VALUES (1, 'Event 1');
INSERT INTO events (id, name) VALUES (2, 'Event 2');
INSERT INTO users (name, id) VALUES ('John', 1);
INSERT INTO users (name, id) VALUES ('Francis', 2);
INSERT INTO users (name, id) VALUES ('Peter', 3);
INSERT INTO users (name, id) VALUES ('Mike', 4);
INSERT INTO availability (answer, event_id, user_id) VALUES ('yes', 1, 1);
INSERT INTO availability (answer, event_id, user_id) VALUES ('yes', 2, 1);
INSERT INTO availability (answer, event_id, user_id) VALUES ('no', 1, 2);
INSERT INTO availability (answer, event_id, user_id) VALUES ('maybe', 2, 4);
You can cross join tables users and events to generate all possible combinations, and then left join table availability. Then, aggregation and a conditional sum() give you the expected result.
select
u.id user_id,
sum(case when a.event_id is null then 1 else 0 end) cnt
from users u
cross join events e
left join availability a
on a.event_id = e.id and a.user_id = u.id
group by u.id
order by u.id
Demo on DB Fiddle:
user_id | cnt
------: | --:
1 | 0
2 | 1
3 | 2
4 | 1
You can also solve this by pre-aggregating the availability table:
select u.user_id, (e.num_events - a.cnt)
from users u left join
(select a.user_id, count(*) as cnt
from availability a
group by a.user_id
) a
on u.user_id = a.user_id cross join
(select count(*) as num_events from events) e;
I have 2 tables.
This is my GroupTable.
CREATE TABLE GroupTable(
ID INT,
GROUPNAME VARCHAR(50),
UnderGroupId INT
);
INSERT INTO GroupTable VALUES (1,'A',0);
INSERT INTO GroupTable VALUES (2,'B',1);
INSERT INTO GroupTable VALUES (3,'C',2);
INSERT INTO GroupTable VALUES (4,'D',3);
Below is the datatable where i'm passing groupId in data table for reference
CREATE TABLE Reference(
ID INT,
GROUPID VARCHAR(50),
GroupValue VARCHAR(50)
);
INSERT INTO Reference VALUES (1,3,'X');
INSERT INTO Reference VALUES (2,4,'Y');
INSERT INTO Reference VALUES (3,1,'Z');
and i want to show the result like this
| ID | GROUPID | GroupValue | GROUPNAME1 | GROUPNAME2 | GROUPNAME3 | GROUPNAME4 |
|----|---------|------------|------------|------------|------------|------------|
| 1 | 3 | X | A | B | C | |
| 2 | 4 | Y | A | B | C | D |
| 3 | 1 | Z | A | | | |
From your comment, you can try to OUTER JOIN by GROUPID > UnderGroupId condition because that condition is those two table relationship condition.
then
UnderGroupId = 0 mean the group1
UnderGroupId = 1 mean the group2
UnderGroupId = 2 mean the group3
UnderGroupId = 3 mean the group4
You can do condition aggregate function on UnderGroupId, to get the pivot result.
TestDLL
CREATE TABLE GroupTable(
ID INT,
GROUPNAME VARCHAR(50),
UnderGroupId INT
);
INSERT INTO GroupTable VALUES (1,'A',0);
INSERT INTO GroupTable VALUES (2,'B',1);
INSERT INTO GroupTable VALUES (3,'C',2);
INSERT INTO GroupTable VALUES (4,'D',3);
CREATE TABLE Reference(
ID INT,
GROUPID VARCHAR(50),
GroupValue VARCHAR(50)
);
INSERT INTO Reference VALUES (1,3,'X');
INSERT INTO Reference VALUES (2,4,'Y');
INSERT INTO Reference VALUES (3,1,'Z');
Query 1:
SELECT t1.ID,
t1.GROUPID,
t1.GroupValue,
coalesce(MAX(CASE WHEN UnderGroupId = 0 THEN tt.GROUPNAME end),'') GROUPNAME1,
coalesce(MAX(CASE WHEN UnderGroupId = 1 THEN tt.GROUPNAME end),'') GROUPNAME2,
coalesce(MAX(CASE WHEN UnderGroupId = 2 THEN tt.GROUPNAME end),'') GROUPNAME3,
coalesce(MAX(CASE WHEN UnderGroupId = 3 THEN tt.GROUPNAME end),'') GROUPNAME4
FROM Reference t1
LEFT JOIN GroupTable tt ON t1.GROUPID > tt.UnderGroupId
GROUP BY t1.ID,
t1.GROUPID,
t1.GroupValue
Results:
| ID | GROUPID | GroupValue | GROUPNAME1 | GROUPNAME2 | GROUPNAME3 | GROUPNAME4 |
|----|---------|------------|------------|------------|------------|------------|
| 1 | 3 | X | A | B | C | |
| 2 | 4 | Y | A | B | C | D |
| 3 | 1 | Z | A | | | |
I have two tables as mentioned below.
user table
id | username | password | status |
1 | Prajna | ***** | active |
2 | Akshata | ***** | active |
3 | Sanjana | ***** | inactive |
test table
id | project_name | created_by (user id) | edited_by (user id) |
1 | Test | 1 | 2 |
2 | Trial | 1 | 1 |
3 | Pro1 | 2 | 2 |
I am trying with below query.
select project_name, user.username from test join user on user.id=test.created_by where user.status='active';
I wanted the result like below
I want to retrieve the result as below
How can I retrieve?
project_name | username(created by) | username (edited by) |
Test | Prajna | Akshata |
Trial | Prajna | Prajna |
Pro1 | Akshata | Akshata |
Try this code.
create table `user`
(
`id` int,
`username` varchar(20),
`password` varchar(20),
`status` varchar(20)
)
insert into `user` (`id`,`username`,`password`,`status`) values
(1, 'Prajna', '*****', 'active'),
(2, 'Akshata', '*****', 'active'),
(3, 'Sanjana', '*****', 'inactive')
create table `test`
(
`id` int,
`project_name` varchar(20),
`created_by` int,
`edited_by` int
)
insert into `test` (`id`,`project_name`,`created_by`,`edited_by`) values
(1, 'Test', 1, 2),
(2, 'Trial', 1, 1),
(3, 'Pro1', 2, 2)
SELECT
`t`.`project_name`,
`ua`.`username` as 'username (created by)' ,
`ub`.`username` as 'username (edited by)'
FROM `test` `t`
JOIN `user` `ua` ON `t`.`created_by` = `ua`.`id`
JOIN `user` `ub` ON `t`.`edited_by` = `ub`.`id`
WHERE
`ua`.`status` = 'active'
AND `ub`.`status` = 'active'
order by `t`.`id`
project_name | username (created by) | username (edited by)
:----------- | :-------------------- | :-------------------
Test | Prajna | Akshata
Trial | Prajna | Prajna
Pro1 | Akshata | Akshata
db<>fiddle here
SELECT
test.project_name, user.username
FROM test
INNER JOIN user
ON user.id = test.created_by
WHERE user.status='active';
PS: you have an error here user.id=test=created_by
.
You need sub-query and join between those two sub-query using join
select project_name,created_by,edited_by from
(
select u.id,project_name, u.username as created_by from user u left join test t1 on
u.id= t1.created_by
where user.status='active'
) Table1
inner join
(
select u.id,project_name, u.username as edited_by from user u left join test t2 on
u.id= t2.created_by
where user.status='active'
) table2 on Table1.project_name=table2.project_name
I know the "how to join the newest record" questions get asked a lot, however, this one exceeds my knowledge. I usually use a "join the max date subquery and then join the row with the matching id and time" approach to the problem, and I can add additional conditions in the where clause of the subquery, but this style doesn't work in this situation.
I am looking for a history of all records in the first table, and to join on the most recent record from the second table before the time of the record from the first.
Example:
CREATE TABLE `A` (
`id` int(11) NOT NULL,
`a_time` timestamp NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `A` (`id`, `a_time`) VALUES
(1, '2018-03-21 04:30:00'),
(2, '2018-03-21 05:30:00'),
(3, '2018-03-21 07:30:00'),
(4, '2018-03-21 12:30:00');
CREATE TABLE `B` (
`id` int(11) NOT NULL,
`b_time` timestamp NOT NULL,
`some_text` varchar(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `B` (`id`, `b_time`, `some_text`) VALUES
(1, '2018-03-21 05:30:00', 'Foo'),
(2, '2018-03-21 09:30:00', 'Bar');
ALTER TABLE `A`
ADD PRIMARY KEY (`id`);
ALTER TABLE `B`
ADD PRIMARY KEY (`id`);
What I'm hoping for is the id and time from A, and the most recent (<=) some_text from B
a.id a.a_time b.some_text
------------------------------------
1 2018-03-21 04:30:00 null
2 2018-03-21 05:30:00 Foo
3 2018-03-21 07:30:00 Foo
4 2018-03-21 12:30:00 Bar
Can someone help me out with this one? Thanks!
I would use a "correlated subquery" like this:
Query 1:
select
a.*
, (select b.some_text from b
where b.b_time <= a.a_time
order by b.b_time DESC
limit 1) as some_text
from a
order by a.id
Results:
| id | a_time | some_text |
|----|----------------------|-----------|
| 1 | 2018-03-21T04:30:00Z | (null) |
| 2 | 2018-03-21T05:30:00Z | Foo |
| 3 | 2018-03-21T07:30:00Z | Foo |
| 4 | 2018-03-21T12:30:00Z | Bar |
I might use an uncorellated subquery, like this:
SELECT x.some
, c.columns
, y.some_column
FROM
( SELECT a.*
, MAX(b.b_time) b_time
FROM a
LEFT
JOIN b
ON b.b_time <= a.a_time
GROUP
BY id
) x
LEFT
JOIN b y
ON y.something = x.something;
+----+---------------------+-----------+
| id | a_time | some_text |
+----+---------------------+-----------+
| 1 | 2018-03-21 04:30:00 | NULL |
| 2 | 2018-03-21 05:30:00 | Foo |
| 3 | 2018-03-21 07:30:00 | Foo |
| 4 | 2018-03-21 12:30:00 | Bar |
+----+---------------------+-----------+
I have 2 tables:
table Companies
+----------+-------------+----+
| Id | MainId | Type | Name |
+----+--------+--------+------+
| 1 | | NO | |
| 2 | 1 | Filial | |
| 3 | | NO | |
| 4 | 3 | Filiar | |
+-------------+--------+------+
table Employees
+------------------+-------+-------+
| Id | Name | CompId| FilId |
+------------------+-------+-------+
| 333| Simon | 1 | |
| 444| John | 1 | 2 |
| 555| Andrew | | 4 |
| 777| Dennis | 11 | |
| 888| John | 3 | 10 |
+------------------+-------+-------+
How can I get all employees that work at companies listed in Companies table?
= At least one row (CompId or FilId) is linked to row in Companies table
How can I get all employees that DON'T work at companies listed in Companies table?
= BOTH CompId or FilId columns DON'T exist in Companies table
I have tried the solution but it doesn't perform well...
1st:
SELECT * FROM `Employees`
INNER JOIN `Companies` ON `Employees`.`FilId` = `Companies`.`Id`
OR `Employees`.`FilId` = `Companies`.`Id`
Added results for SHOW CREATE TABLE table_name
Removed unused columns
CREATE TABLE `Employees` (
`Id` varchar(10) NOT NULL,
`Name` varchar(255) NOT NULL
`CompId` varchar(10) NOT NULL,
`FilId` varchar(10) NOT NULL,
PRIMARY KEY (`Id`),
KEY `empl_to_comps` (`VuzId`),
KEY `empl_to_fils` (`FilId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `Companies` (
`Id` varchar(10) NOT NULL DEFAULT '',
`MainId` varchar(10) DEFAULT '',
`Type` varchar(255) NOT NULL,
`Name` varchar(255) NOT NULL
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
SELECT DISTINCT e.*
FROM Employees e
JOIN Companies c ON c.Id IN (e.CompId, FilId);
SELECT e.*
FROM Employees e
LEFT JOIN Companies c ON c.Id IN (e.CompId, FilId)
WHERE c.Id IS NULL;
Update
Depending on data and indexes the following two queries might be faster. And though verbose, they are more expressive than the JOIN queries.
SELECT e.*
FROM Employees e
WHERE EXISTS (
SELECT *
FROM Companies c
WHERE c.Id = e.CompId
)
OR EXISTS (
SELECT *
FROM Companies c
WHERE c.Id = e.FilId
);
SELECT e.*
FROM Employees e
WHERE NOT EXISTS (
SELECT *
FROM Companies c
WHERE c.Id = e.CompId
)
AND NOT EXISTS (
SELECT *
FROM Companies c
WHERE c.Id = e.FilId
);