Left join how can i use where if right field exists - mysql

i have two tables:
users (used fields in query) ->
|uuid|name|last_name|email|rol |status|
|1234|abcd| abc |1#2.3|pre-thunder| 1 |
|5678|efgh| efg |4#5.6|pre-thunder| 1 |
And documentation_thunder table (used fields in query)->
|id|id_thunder|doc_type|
|1 |1234 |image |
I try to get all records on my left table but additional i get a count from my right table:
SELECT
users.uuid,
users.email,
users.name,
users.last_name,
COUNT(documentation_thunder.id) as documentation// i need to know how many documents have the user
FROM users
LEFT JOIN documentation_thunder
ON users.uuid = documentation_thunder.id_thunder
WHERE
users.status = 1 AND users.rol = 'pre-thunder' AND (documentation_thunder.doc_type = 'image' OR documentation_thunder.doc_type IS NULL)
This query only returns first user but i need returns all users no matter if not have documents.
Any idea? how do i do it?

Since you want to return a count for each user, you should also be using group by. Perhaps this is what you're after:
SELECT
users.uuid,
users.email,
users.name,
users.last_name,
COUNT(documentation_thunder.id) as documentation
FROM users
LEFT JOIN documentation_thunder
ON users.uuid = documentation_thunder.id_thunder
WHERE
users.status = 1 AND users.rol = 'pre-thunder' AND
(documentation_thunder.doc_type = 'image' OR documentation_thunder.doc_type IS NULL)
GROUP BY users.uuid

Related

How to use IF statement before FROM Clause

I have three tables:
Users and companies can add feeds. The flag columns means
0 = user
1 = company
How can I perform this SQL query correctly? Thanks in advance for your help!
SELECT
feeds.feeds_id,
feeds.title
IF feeds.flag = 0
FROM user
INNER JOIN
feeds.user_or_company = user.user_id
ELSEif feeds.flag = 1
INNER JOIN
feeds.user_or_company = company.company_id
One way to solve this is to LEFT JOIN to both user and company tables and then select the appropriate name value based on feeds.flag:
SELECT f.feeds_id, f.title,
CASE f.flag WHEN 0 THEN u.name ELSE c.name END AS name
FROM feeds f
LEFT JOIN user u ON u.user_id = f.user_or_company
LEFT JOIN company c ON c.company_id = f.user_or_company
Output (for your sample data)
feeds_id title name
2 This title added twice by user User-1
3 This title added by company Company-2
1 This title added by user User-3
Demo on dbfiddle

Error on using outer query column in subquery for date constraint

We have a Mariadb table with users details in (users)
We have a 2nd table for review dates (reviewdates)
| reviewID |USERID |A review date |
| 001 | 123 |2017-01-08 09:02:10 |
etc...
That records review meeting dates against each user.
We have a 3rd table (userdata) with multiple types of user data in. Field id 101 is new targets for the review. Field id 98 is old targets from the previous review.
|dataID|Userid |Field ID |FieldValue |UpdatedOn |UpdatedBy|
-------------------------------------------------------------
|0001 |123 | 101 |my new target|2017-01-10|145 |
|0002 |123 | 98 |my old target|2017-01-10|0 |
New Target (field ID 101) gets copied to old targets (field id 98) when the review is completed.
Either field can be updated at any time.
Each user has many review dates. I need to compare the first value of the old field after the review is complete with the last value before the review date to make sure they have copied over correctly. As users can change either field it has to a comparison of immediately before and after the completion process.
so I join users and reviewdates
select users.userid,users.username,reviewdates.meetingdate
from companyusers users
join reviewdates on reviewdates.userid = users.userid
and this gives me all the review dates for all users
I then tried to find the most recent entry for the 101 field :
select users.userid,users.username, reviewdates.meetingdate, latest101.fielddetails,latest101.updatedon
from users
join reviewdates on reviewdates.userid = users.userid
left join (select userdata.* from userdata u1
where u1.fieldid = 101
and u1.updatedOn = (select max(u2.updatedon)
from userdata u2
where u1.userid = u2.userid
and u2.fieldid = 101)
) as latest101 on (latest101.userid = users.userid)
and this works OK too but when I try to find the most recent entry before each review date:
select users.userid,users.username,reviewdates.meetingdate,latest101.fielddetails,latest101.updatedon
from users
join reviewdates on reviewdates.userid = users.userid
left join (select userdata.* from userdata u1
where u1.fieldid = 101
and u1.updatedOn = (select max(u2.updatedon)
from userdata u2
where u1.userid = u2.userid
and u2.fieldid = 101
#date limit
and u2.updatedOn < reviewdates.meetingdate)
) as latest101 on (latest101.userid = users.userid)
I get an
"unknown column reviewdates.meetingdate in where clause"
error. I've found loads of statements saying I can't refer to an outer join in a subquery but none that provide possible answers that apply to these date constraints.
Any help or pointers would be appreciated.
I do not see that you are filtering the most outer 'reveiwdates' table with anything specific, it is just used to display the 'meetingdate' based on the inner queries,
in that case firstly, there is no reason to use the same reference inside subquery.
Secondly, there are so many 'meetingdates', which specific meeting date are we comparing against the 'updatedOn' ?
You cannot join two tables on an in-equality condition.
Either a constant review date filter needs be applied or a procedure needs be written to loop through each meeting date for a user in the 'reviewdates' table.
If you just care about the latest review for that user then you could fetch and compare the latest 'reviewdate' just like how you are comparing the latest updated on, 'updatedOn' does not seem to have time component and to avoid other issues use date() or equivalent while comparing.
select users.userid,users.username,reviewdates.meetingdate,latest101.fielddetails,latest101.updatedon
from users
join reviewdates on reviewdates.userid = users.userid
left join (select userdata.* from userdata u1
where u1.fieldid = 101
and u1.updatedOn = (select max(u2.updatedon)
from userdata u2
where u1.userid = u2.userid
and u2.fieldid = 101
#date limit
and u2.updatedOn < (select date(max(reviewdates.meetingdate)) from reviewdates where u2.userid = reviewdates.userid))
) as latest101 on (latest101.userid = users.userid)

Selecting data for 1 specific user from multiple tables

So my database is composed of 5 tables with different columns for each one. The only column that keeps them all identified is the id. I'm trying to get the data for a specific user, but I only seem to get all users of the database instead.
This is what I have tried:
SELECT
ControlAccess.UserName,
ControlAccess.Pass,
Users.First_Name,
Users.Last_Name,
UserInfo.Age,
UserInfo.Country,
UserInfo.Address,
UserInfo.ZipCode,
Sessions.Matrix1,
Sessions.Matrix2,
Sessions.Result,
Operations.Operation,
FilePath.LocationFiles
FROM
MatrixUsers.UserInfo
INNER JOIN
MatrixUsers.Users
ON
UserInfo.idUserInfo = Users.idUsers = 1
INNER JOIN
MatrixUsers.ControlAccess
ON
ControlAccess.idControlAccess = UserInfo.idUserInfo = 1
INNER JOIN
MatrixUsers.Sessions
ON
Sessions.idSessions = ControlAccess.idControlAccess = 1
INNER JOIN
MatrixUsers.FilePath
ON
FilePath.idFilePath = Sessions.idSessions = 1
INNER JOIN
MatrixUsers.Operations
ON
Operations.idOperations = FilePath.idFilePath = 1;
I tried putting 1 at the end of each id to see if they matched, but I still get all the users.
I'm new to SQL and I'm only familiar with matching rows, but not choosing specific one.
Here are the columns of each table:
ControlAccess: {idControlAccess, UserName, Pass}
Sessions: {idSessions, Matrix1, Matrix2, Result}
FilePath: {idFilePath, LocationFiles}
Operations: {idOperation, Operation}
UserInfo: {idUserInfo, Age, Country, Address, ZipCode, Phone}
Use WHERE when you want specific user. for example, select user_id from table where user_id=the_specific_user_id . Follow this basic to built you complicate statement.
Just user where after all the joins
WHERE ANY_COLUMN_REFER_TO_USER_ID = YOUR_NEEDED_ID
so your full query would be like :
SELECT
ControlAccess.UserName,
ControlAccess.Pass,
Users.First_Name,
Users.Last_Name,
UserInfo.Age,
UserInfo.Country,
UserInfo.Address,
UserInfo.ZipCode,
Sessions.Matrix1,
Sessions.Matrix2,
Sessions.Result,
Operations.Operation,
FilePath.LocationFiles
FROM MatrixUsers.UserInfo
INNER JOIN MatrixUsers.Users
ON UserInfo.idUserInfo = Users.idUsers
INNER JOIN MatrixUsers.ControlAccess
ON ControlAccess.idControlAccess = UserInfo.idUserInfo
INNER JOIN MatrixUsers.Sessions
ON Sessions.idSessions = ControlAccess.idControlAccess
INNER JOIN MatrixUsers.FilePath
ON FilePath.idFilePath = Sessions.idSessions
INNER JOIN MatrixUsers.Operations
ON Operations.idOperations = FilePath.idFilePath
WHERE UserInfo.idUserInfo = 1

How to build query from other queries

I want to create a query that will list all users and their profile information, however the profile info has to be gotten using a rather complex procedure.
SELECT options.`value` FROM users
RIGHT JOIN profile on(profile.uid = users.uid)
RIGHT JOIN field_data_field_ethnicity on(field_data_field_ethnicity.entity_id = profile.pid)
RIGHT JOIN options on(field_data_field_city.field_ethnicity_value = bdc_options.`index` AND bdc_options.`key` = "ethnicity")
WHERE users.uid = 1 #needs to go through all users in table
ORDER BY field_data_field_ethnicity.revision_id DESC
LIMIT 1
SELECT options.`value` FROM users
RIGHT JOIN profile on(profile.uid = users.uid)
RIGHT JOIN field_data_field_city on(field_data_field_city.entity_id = profile.pid)
RIGHT JOIN options on(field_data_field_city.field_city_value = bdc_options.`index` AND bdc_options.`key` = "city")
WHERE users.uid = 1
ORDER BY field_data_field_ethnicity.revision_id DESC
LIMIT 1
Just going from these two fields, how would I go through the users table and get something like
USER | CITY | ETHNICITY
1 | London | Koalabear
2 | Paris | Fiddle
Here are the tables in question: http://pastebin.com/feNvzMZw
The field table has all the entries with a entity_id that refers to the profile table and a revision id which refers to the revision number.. I always need the highest to be up to date

How to do this simple MySQL statement without resorting to a sub query?

Users table:
user_id | avatar
----------------------------------
1 | file-name.jpg
2 | friendly-ghost.jpg
Profile views table:
profile_user_id | viewer_user_id
--------------------------------
2 | 1
I need to get all the information about the user who user 1 viewed.
The query:
SELECT *
FROM `profile_views`
INNER JOIN `users` ON profile_views.viewer_user_id = users.user_id
WHERE profile_views.viewer_user_id = '1'
This gives back:
profile_user_id: 2
avatar: file-name.jpg
As you can see it's giving back user 1's avatar not user 2's. I need it to give back the avatar of the user that user 1 viewed. In this case that would be "friendly-ghost.jpg".
Is there a way to do this without resorting to a sub query?
SELECT user_id, avatar
FROM profile_views AS PV
INNER JOIN users AS U ON U.user_id = PV.profile_user_id
WHERE PV.viewer_user_id = 1
SELECT * FROM users
JOIN profile_views ON (profile_user_id = user_id AND viewer_user_id = 1)
Just change your join condition will work.
ON profile_views.profile_user_id = users.user_id