I've 3 tables tb1, users, users_credits.
My gol is to combine two select (sel1, sel2) into a single view and
display 0 in the sel2 where there isn't rows (left join?)
sel1
SELECT
users.userid,
users.datareg,
users_credits.credits,
FROM
users,
users_credits,
WHERE
users.userid = users_credits.userid
Sel2
SELECT COUNT(*) FROM tb1 where tb1.id_user = users.userid
table structure
tb1
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_user` decimal(11,0) NOT NULL,
`datains` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
users
`userid` int(4) unsigned NOT NULL AUTO_INCREMENT,
`datareg` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`userid`)
users_credits
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(11) NOT NULL,
`credits` decimal(5,0) NOT NULL,
`data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
What is the best way to do this?
Thanks.
SELECT users.userid,
users.datareg,
users_credits.credits,
COALESCE(c.totalCount,0) totalCount
FROM users
LEFT JOIN users_credits
ON users.userid = users_credits.userid
LEFT JOIN
(
SELECT id_user, COUNT(*) totalCount
FROM tb1
GROUP BY id_user
) c ON c.id_user = users.userid
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
UPDATE 1
SELECT users.userid,
users.datareg,
users_credits.credits,
COALESCE(c.totalCount,0) totalCount,
c.max_datains
FROM users
LEFT JOIN users_credits
ON users.userid = users_credits.userid
LEFT JOIN
(
SELECT id_user, MAX(datains) max_datains, COUNT(*) totalCount
FROM tb1
GROUP BY id_user
) c ON c.id_user = users.userid
UPDATE 2
you need to create two views for this:
1st View:
CREATE VIEW tbl1View
AS
SELECT id_user, MAX(datains) max_datains, COUNT(*) totalCount
FROM tb1
GROUP BY id_user
2nd View
CREATE VIEW FullView
AS
SELECT users.userid,
users.datareg,
users_credits.credits,
COALESCE(c.totalCount,0) totalCount,
c.max_datains
FROM users
LEFT JOIN users_credits
ON users.userid = users_credits.userid
LEFT JOIN tbl1View c ON c.id_user = users.userid
Related
My two tables are as follows :
Table 1 : Transaction
TRANS_ID (primary key), TRANS_DATE, TRANS_STATUS, USER_ID (Foreign_Key)
The same user_id will be repeated when status change
Table 2 : Users
USER_ID (Primary_Key), USER_NAME, USER_DOB, OTHER_INFO
I want to get the user information along with last transaction status.
I am familiar with the following query.
SELECT MAX(Transaction.TRANS_DATE),Transaction.TRANS_STATUS, Users.USER_NAME, Users.USER_DOB
FROM Users
INNER_JOIN Transaction ON Transaction.USER_ID = Users.USER_ID
WHERE Transaction.USER_ID = #UserID
I pass the UserID with Parameter.AddWithValue. Unfortunately, this method does not return the TRANS_STATUS for the MAX(TRANS_DATE). It does return MAX(TRANS_DATE) but TRANS_STATUS is the first occurrence, not the corresponding STATUS to MAX(TRANS_DATE) record.
Please let me know how I could get the TRANS_STATUS for the MAX(TRANS_DATE). I prefer using INNER JOIN but recommendations are appreciated.
I could not still get to working.
Here are my table scripts.
CREATE TABLE `Transactions` (
`TRANS_ID` int(11) NOT NULL,
`TRANS_DATE` datetime NOT NULL,
`TRANS_STATUS` varchar(45) NOT NULL,
`USER_ID` int(11) NOT NULL,
PRIMARY KEY (`TRANS_ID`),
UNIQUE KEY `TRANS_ID_UNIQUE` (`TRANS_ID`),
KEY `USER_ID_idx` (`USER_ID`),
CONSTRAINT `USER_ID` FOREIGN KEY (`USER_ID`) REFERENCES `Users` (`USER_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `Users` (
`USER_ID` int(11) NOT NULL AUTO_INCREMENT,
`USER_NAME` varchar(45) NOT NULL,
`USER_DOB` datetime NOT NULL,
`OTHER_INFO` varchar(45) NOT NULL,
PRIMARY KEY (`USER_ID`),
UNIQUE KEY `USER_ID_UNIQUE` (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
If I understood right this could work for you
SELECT A.USER_ID AS USER_ID, A.TRANS_DATE AS TRANS_DATE, TRANS_STATUS, USER_NAME, USER_DOB
FROM
(SELECT USER_ID, MAX(TRANS_DATE) AS TRANS_DATE FROM TRANSACTION
GROUP BY USER_ID) A
INNER JOIN
(SELECT USER_ID, TRANS_DATE, TRANS_STATUS FROM TRANSACTION) B
ON A.USER_ID = B.USER_ID
AND A.TRANS_DATE=B.TRANS_DATE
INNER JOIN USERS U
ON A.USER_ID=U.USER_ID;
SELECT Users.USER_NAME, Users.USER_DOB
FROM Users usr INNER JOIN(
SELECT Transaction.TRANS_STATUS, MAX(Transaction.TRANS_DATE)
FROM Transaction GROUP BY Transaction.TRANS_STATUS) trs ON trs.USER_ID=usr.USER_ID
You can use LAST_VALUE function
SELECT Top 1
u.User_ID
,u.user_name
,u.user_dob
,u.other_info
,LAST_VALUE(t.Trans_Date) OVER (PARTITION BY t.user_id ORDER BY
t.Trans_Date RANGE BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING) AS Max_Tran_Date
,LAST_VALUE(t.trans_status) OVER (PARTITION BY t.user_id ORDER BY
t.Trans_Date RANGE BETWEEN UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING) as Last_Status
FROM #Users as u
INNER JOIN #Transaction as t ON t.user_id = u.user_id
WHERE u.User_ID = #UserID
You could use a join on the subquery for max TRANS_DATE
select t.max_trans, t.USER_NAME, t.USER_DOB
from Transaction
INNER JOIN
(
SELECT MAX(Transaction.TRANS_DATE) max_trans,
Transaction.USER_ID, Users.USER_NAME, Users.USER_DOB
FROM Users
INNER_JOIN Transaction ON Transaction.USER_ID = Users.USER_ID
WHERE Transaction.USER_ID = #UserID
) t on Transaction.USER_ID = t.USER_ID and t.max_trans = Transaction.TRANS_DATE
I have a conversation table which contains two users ids as foreign keys, and the user table which contains the users details. I want to write a query which returns the conversation table joined to the user table but displaying the name and surname of the user whose id wasn't sent as the parameter.
CREATE TABLE `conversation` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_one_id` int(11) NOT NULL,
`user_two_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`surname` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
)
For example I have
Conversation:
id user_one_id user_two_id
1 1 2
User:
id name surname
1 userone_name userone_surname
2 usertwo_name usertwo_surname
I want a query that will return user_two's name and surname in the join, not user one.
My current query:
SELECT c.id, c.user_one_id, c.user_two_id, u.name, u.surname * FROM conversation c
JOIN user u
WHERE c.user_one_id = 1
OR c.user_two_id = 1
AND IF (c.user_one_id = u.id, c.user_two_id = u.id, c.user_one_id = u.id)
GROUP BY c.id
ORDER BY c.date DESC;
[INNER] JOIN should have an ON clause. (I consider it a flaw that MySQL allows you to omit it.)
The join criteria would have to be: Give me the user of the conversation that is not user 1.
SELECT c.id, c.user_one_id, c.user_two_id, u.name, u.surname
FROM conversation c
JOIN user u ON u.id IN (c.user_one_id, c.user_two_id) AND u.id <> 1
WHERE c.user_one_id = 1 OR c.user_two_id = 1
ORDER BY c.date DESC;
This might be easy but I don't have enough experience with mysql, I have four tables:
employee
user
privilege
page
I want to select from these four tables the following:
emoloyeeName
UserId
count(privilege)
count(pages)
so I want my query to display each employee user name, number of granted user privileges and number of pages created by the user
my tables structure goes as follows:
CREATE TABLE IF NOT EXISTS `employee` (
`ID` int(11) NOT NULL,
`EMP_ENG_NAME_P1` varchar(15) DEFAULT NULL,
`EMP_ENG_NAME_P2` varchar(15) DEFAULT NULL,)
ALTER TABLE `employee`ADD PRIMARY KEY (`ID`);
CREATE TABLE IF NOT EXISTS `users` (
`ID` int(11) NOT NULL,
`USER_ID` varchar(30) DEFAULT NULL,
`USER_EMP` int(11) DEFAULT NULL,)
ALTER TABLE `users`ADD PRIMARY KEY (`ID`),
ADD UNIQUE KEY `USER_ID` (`USER_ID`),
ADD KEY `users_ibfk_1` (`USER_EMP`);
CREATE TABLE IF NOT EXISTS `privileg` (
`ID` int(11) NOT NULL,
`USER_ID` int(11) DEFAULT NULL,
`PAGE_ID` int(11) DEFAULT NULL,)
ALTER TABLE `privileg`ADD PRIMARY KEY (`ID`);
ALTER TABLE `privileg` ADD CONSTRAINT `privileg_ibfk_2`
FOREIGN KEY (`USER_ID`) REFERENCES `users` (`ID`)
ON DELETE CASCADE ON UPDATE CASCADE;
CREATE TABLE IF NOT EXISTS `pages` (
`ID` int(11) NOT NULL,
`userCreatorID` int(11) DEFAULT NULL,
`PAGE_ENG_DESC` varchar(100) DEFAULT NULL,)
I was able to construct two queries that display the the same result seperated once with the privilege count for each user and once with the page count for each user
first query:
select employee.EMP_ENG_NAME_P1, employee.EMP_ENG_NAME_P2, users.USER_ID, COUNT(privileg.ID)
from employee
INNER JOIN users on users.USER_EMP = employee.EMP_ID
INNER JOIN privileg on users.ID= privileg.USER_ID
GROUP BY users.ID
second query:
select employee.EMP_ENG_NAME_P1, employee.EMP_ENG_NAME_P2, users.USER_ID, users.ID, COUNT(pages.ID)
from employee
INNER JOIN users on users.USER_EMP = employee.EMP_ID
INNER JOIN pages on users.ID = pages.userCreatorID
GROUP BY users.ID
What I need now is to combine them together,like the following image
I use the following query:
select employee.EMP_ENG_NAME_P1,employee.EMP_ENG_NAME_P2, users.USER_ID, users.ID, COUNT(pages.ID), COUNT(privileg.ID)
from employee
INNER JOIN users on users.USER_EMP=employee.EMP_ID
INNER JOIN privileg on users.ID= privileg.USER_ID
INNER JOIN pages on users.ID= pages.userCreatorID
GROUP BY users.ID
but the count result is not correct, it is multiplied
any ideas?
try it-
SELECT emp.EMP_ENG_NAME_P1, emp.EMP_ENG_NAME_P2, usr.USER_ID, COUNT(DISTINCT prv.ID), COUNT(DISTINCT pgs.id)
FROM employee emp
INNER JOIN users usr ON usr.USER_EMP = emp.EMP_ID
INNER JOIN privileg prv ON usr.ID= prv.USER_ID
INNER JOIN pages pgs ON usr.ID= pgs.UserCreatorID
GROUP BY users.ID
Try:
SELECT employee.EMP_ENG_NAME_P1, employee.EMP_ENG_NAME_P2, users.USER_ID, COUNT(privileg.ID), COUNT(pages.ID)
FROM employee
INNER JOIN users on users.USER_EMP = employee.EMP_ID
INNER JOIN privileg on users.ID= privileg.USER_ID
INNER JOIN pages on users.ID = pages.userCreatorID
GROUP BY users.ID
I've got the SQL query below:
SELECT message, sent_date, user_id
FROM messages
LEFT JOIN numbers ON messages.from_id = numbers.id
It returns all the rows (about 4000) in the messages table with additional columns coming from the numbers table. So far, this is what I would expect.
Now I left join this sub-query to another table, again using a left join:
SELECT message, sent_date
FROM (
SELECT message, sent_date, user_id
FROM messages
LEFT JOIN numbers ON messages.from_id = numbers.id
) AS table1
LEFT JOIN users ON table1.user_id = users.id
However, it only returns about 200 rows so many are missing. Since this is a left join I would expect all the rows from table1 to be in the result. Can anybody see what the issue is?
Edit:
So for information here are the 3 relevant tables (with irrelevant columns removed):
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`message` text CHARACTER SET utf8 NOT NULL,
`from_id` int(11) DEFAULT NULL,
`sent_date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `from_id` (`from_id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=101553 ;
CREATE TABLE IF NOT EXISTS `numbers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`number` varchar(32) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6408 ;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(256) CHARACTER SET utf8 DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2395 ;
You can try alternative method to debug the issue:
CREATE TEMPORARY table tmp1 AS SELECT message, sent_date, user_id
FROM messages
LEFT JOIN numbers
ON messages. from_id = numbers.id;
and then see whether this query works.
SELECT message, sent_date
FROM tmp1 table1
LEFT JOIN users
ON table1.user_id = users.id;
Also for your case make sure that there are no other insert or updates in between. otherwise use transactions.
table1 sometimes won't have a UserID - so that'll be null, so those results will be missing?
I don't have an exact answer to your question, but if I have to start thinking, I will first find out what 3800 rows are missing and try to see the pattern (is it because user_id are null or duplicate)
SELECT message, sent_date, user_id
FROM messages
LEFT JOIN numbers ON messages.from_id = numbers.id
MINUS
(SELECT table1.message, table1.sent_date, table1.user_id
FROM (
SELECT message, sent_date, user_id
FROM messages
LEFT JOIN numbers ON messages.from_id = numbers.id
) AS table1
LEFT JOIN users ON table1.user_id = users.id)
Try this, I think it's a scoping issue on user_id.
SELECT table1.message, table1.sent_date
FROM (
SELECT messages.message, messages.sent_date, numbers.user_id
FROM messages
LEFT JOIN numbers ON messages.from_id = numbers.id
) AS table1
LEFT JOIN users ON table1.user_id = users.id
I'm not sure if user_id is in messages or numbers.
There is no way this should happen.
Try this variation:
SELECT
m.message, m.sent_date, n.user_id
FROM
messages m
LEFT JOIN
numbers AS n ON m.from_id = n.id
LEFT JOIN
users AS u ON n.user_id = u.id ;
i have bookings table which has two people- i want to return person_1 as a row, person_2 as a new row but with the person's id related to the people table
This is as far as i got-but doesnt pull in booking info
SELECT people.* FROM (
(select booking.person_1 as id from booking)
union ALL
(select booking.person_2 as id from booking)
) as peopleids
join people on people.id = peopleids.id;
heres my structure
CREATE TABLE IF NOT EXISTS `booking` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`slot` enum('morning_drive','afternoon_loop','return_drive') NOT NULL,
`type` enum('911','vintage_911') NOT NULL,
`car` int(11) NOT NULL,
`person_1` int(11) DEFAULT NULL,
`person_2` int(11) DEFAULT NULL,
`dated` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
CREATE TABLE IF NOT EXISTS `people` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`organisation` varchar(100) NOT NULL,
`event_date` date NOT NULL,
`wave` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
any ideas on how i could get a result set like- person.first_name, person.last_name, person.organisation, booking.dated, person.car, person.slot. im struggling with having two fields and having them to relate them into the one list
update for anyone interested in this and joining a 3rd table
heres my final query with php vars to pull in my certain dates and slots and also join a third table
SELECT peopleids.id,
peopleids.car,
cars.nr,
p.first_name,
p.last_name,
p.organisation,
p.event_date,
p.wave
FROM (SELECT booking.car, booking.person_1 as id FROM booking WHERE booking.dated = '".$date."' AND booking.`slot` = '".$slot."'
union ALL SELECT booking.car, booking.person_2 as id FROM booking WHERE booking.dated = '".$date."' AND booking.`slot` = '".$slot."'
) as peopleids
LEFT JOIN people p ON p.id = peopleids.id LEFT JOIN cars on cars.id = peopleids.car;
SELECT
ag.id,
p.first_name,
p.last_name,
p.organisation,
p.event_date,
p.wave
FROM (
SELECT booking.person_1 as id, booking.Car as car FROM booking
union ALL
SELECT booking.person_2 as id, booking.Car as car FROM booking
) as ag
JOIN people p ON people.id = ag.id;
INNER | LEFT JOIN Cars c ON c.ID = ag.car
select people.first_name as firstname,
people.last_name as lastname,
people.organisation,
booking.dated,
booking.car,
booking.slot from booking
left join people on booking.person_1 = people.id
OR
select people.first_name as firstname,
people.last_name as lastname,
people.organisation,
booking.dated,
booking.car,
booking.slot
from booking
left join people on booking.person_1 = people.id or booking.person_2 = people.id
check that...if you still need help will help you