Count field, joins, multiple selects - mysql

I have three tables. Estimates, Estimate_versions, and customers.
Here is some SQL
SELECT estimates.id,
estimates.estimate_number,
estimates.description,
estimates.meeting_date,
estimates.job_date,
estimates.status,
estimates.price
FROM
(estimates)
LEFT OUTER JOIN estimate_versions estimate_versions ON estimate_versions.estimate_id = estimates.id
LEFT OUTER JOIN customers customers ON customers.id = estimates.customer_id
WHERE customers.key = 'JsB4ND90bn'
This works -- What I want to do is add a field at the very end of the table.
Essentially, I want it to 'count', the number of records in estimate_versions, that contain the current rows, estimate.id, here is some non-working pseudocode of what I basically want in the final field
count(where estimate_versions.estimate_id = estimates.id)
When I try and do a few different ways of achieving this, I usually get ONE row of data, with one number in it. Instead of lets say, 3 records, and the count field containing the appropriate number.
Looking forward to receiving some much needed aid, my SQL skills are weak.

I think this is what you are looking for.
SELECT estimates.id,
estimates.estimate_number,
estimates.description,
estimates.meeting_date,
estimates.job_date,
estimates.status,
estimates.price,
count(estimate_versions.estimate_id)
FROM
(estimates)
LEFT OUTER JOIN estimate_versions estimate_versions ON estimates.id = estimate_versions.estimate_id
LEFT OUTER JOIN customers customers ON estimates.customer_id = customers.id
WHERE customers.key = 'JsB4ND90bn'
group by
estimates.id,
estimates.estimate_number,
estimates.description,
estimates.meeting_date,
estimates.job_date,
estimates.status,
estimates.price

Related

Joining the same table twice in MYSQL

I am trying to create a MYSQL query that pulls in data from a range of tables. I have a master bookings table and an invoice table where I am recording invoice id's etc from Stripe.
I am storing two invoices per booking; one a deposit, the second the final balance.
In my admin backend I then display to the admin info on whether the invoice is paid etc so need to pull in data from SQL to show this.
I'm following some previous guidance here What's the best way to join on the same table twice?.
My query is returning data, however when the invoices table is included twice (to give me the deposit and balance invoices) however the column names are identical.
Could someone point me in the right direction? I think I need to somehow rename the columns on the second returned invoice??? Sorry new to anything but basic SQL queries.
This is my SQL
SELECT * FROM bookings
INNER JOIN voyages ON bookings.booking_voyageID = voyages.voyage_id
LEFT JOIN emailautomations ON bookings.booking_reference = emailautomations.automation_bookingRef AND emailautomations.automation_sent != 1
LEFT JOIN invoices ON bookings.booking_stripeDepositInvoice = invoices.invoice_id
LEFT JOIN invoices inv2 ON bookings.booking_stripeBalanceInvoice = inv2.invoice_id
Thanks to #Algef Almocera's answer I have amended my SQL (and stopped being lazy by using SELECT *, was able to trim loads of columns down to not many!)
SELECT
bookings.booking_status,
bookings.booking_reference,
bookings.booking_stripeCustomerReference,
bookings.booking_stripeDepositInvoice,
bookings.booking_stripeBalanceInvoice,
bookings.booking_totalPaid,
bookings.booking_voyageID,
bookings.booking_firstName,
bookings.booking_lastName,
bookings.booking_contractName,
bookings.booking_contractEmail,
voyages.voyage_id,
voyages.voyage_name,
voyages.voyage_startDate,
depositInvoice.invoice_id AS depositInvoice_id,
depositInvoice.invoice_status AS depositInvoice_status,
balanceInvoice.invoice_id AS balanceInvoice_id,
balanceInvoice.invoice_status AS balanceInvoice_status
FROM bookings
INNER JOIN voyages ON bookings.booking_voyageID = voyages.voyage_id
LEFT JOIN emailautomations ON bookings.booking_reference = emailautomations.automation_bookingRef AND emailautomations.automation_sent != 1
LEFT JOIN invoices depositInvoice ON bookings.booking_stripeDepositInvoice = depositInvoice.invoice_id
LEFT JOIN invoices balanceInvoice ON bookings.booking_stripeBalanceInvoice = balanceInvoice.invoice_id
This, sometimes, couldn't be avoided as keywords might actually often be the same but of different purpose per table. To help with that, you can use aliases. for example:
SELECT
invoices.column_name AS invoices_column_name,
transactions.column_name AS transactions_column_name
FROM invoices ...
LEFT JOIN transactions ...

Retrieving uniq records with union in mysql

I have two tables usersin and usersout(I can not change schema, a lot of system changes must be done in php otherwise). I should get all user records in a query but I should mark them if they are in or out also a user may have an in record and out record I shouldn't show in record if has an out record.
I have created tables with sample data in SQL Fiddle: http://www.sqlfiddle.com/#!9/ac99a/1/0
Can u help me how can I remove duplicates of user records in this union query?
If you want to have all entries with an entry in either the in or out table, but not in both of them, then a full outer join would be your friend.
Since MySQL does not know that kind of join, you can emulate it with a left outer join and a right outer join combined like so:
SELECT
ui.id, ui.user, 'i'
FROM
usersIN ui
LEFT OUTER JOIN
usersOUT uo ON ui.user = uo.user
WHERE uo.id IS NULL
UNION
SELECT
uo.id, uo.user, 'o'
FROM
usersIN ui
RIGHT OUTER JOIN
usersOUT uo ON ui.user = uo.user
WHERE ui.id IS NULL;
This should give you the right output.
A good visual explanation of joins can be found here

LEFT JOIN two columns from one table on two separate tables

I'm not sure if this is possible exactly as stated in the title, but what I'm trying to accomplish, however possible, is what would amount to left joining two columns from one table, each on a separate table.
Here's the statement I'm working with. Unfortunately, MySQL doesn't allow me to actually do this and gives me an error message. Is there another way to accomplish what I want? Is my syntax perhaps just off?
select h.HITTER_ID, u.UMPIRE_ID, u.HAND_B
from
hitters h,
schedules sched
LEFT JOIN
umpires u
ON sched.home_base_umpire_id = u.UMPIRE_ID and h.HAND_B = u.HAND_B
In the umpires table, each UMPIRE_ID appears twice, once with HAND_B = "R" and once with HAND_B = "L"
Essentially, I want to:
1) Pull the UMPIRE_ID from umpires when that UMPIRE_ID appears in schedules
2) Of the two UMPIRE_ID records, select the one with the HAND_B field that corresponds to the HAND_B field in hitters
I could put the "h.HAND_B = u.HAND_B" in the where clause, but that would require that the UMPIRE_ID not be NULL, and I need to leave open the possibility that it is NULL.
How can I accomplish this?
You need to modify your query to be like below
select h.HITTER_ID,
u.UMPIRE_ID,
u.HAND_B
from hitters h
left join umpires u on h.HAND_B = u.HAND_B
left join schedules sched ON sched.home_base_umpire_id = u.UMPIRE_ID;

MySQL LEFT JOIN with optional value in second table

I have two tables: projects and user_licenses.
I'd like to grab the entire list of projects from the database, as well as the user's current license state. The licenses table has a user ID field which I check against a $_SESSION variable for the value. The thing is, they might not have a license, or a non-logged in visitor may want to see the projects list. My question is this: How can I get the data from the left table always display, but only grab data for that row from the right table when certain conditions are met?
The query I have at the moment is this:
SELECT Projects.*,
UserLicenses.*
FROM Projects
LEFT JOIN UserLicenses ON Projects.id = UserLicenses.project_id
WHERE UserLicenses.user_id = 12
ORDER BY name ASC
Add any extra conditions to the on clause of the left join. They will only affect the joined table.
SELECT Projects.*,
UserLicenses.*
FROM Projects
LEFT JOIN UserLicenses
ON Projects.id = UserLicenses.project_id
and UserLicenses.user_id = 12
and UserLicences.Question = '6*7'
and UserLicences.Answer = 42
ORDER BY name ASC
This will return projects without matching licenses.
Move the UserLicenses condition away from WHERE, and up to the JOIN condition. By having it in the WHERE part, you will never see those "left" rows because they are filtered away.
You can also probably use WHERE (UserLicenses.user_id = 12 OR UserLicenses.user_id IS NULL)
Don't do that. Just move it to the join condition like this:
LEFT JOIN UserLicenses ON
(Projects.id = UserLicenses.project_id AND UserLicenses.user_id = 12)
You can use LEFT JOIN
If its conditions match then values show otherwise null value shows.

How do I decide when to use right joins/left joins or inner joins Or how to determine which table is on which side?

I know the usage of joins, but sometimes I come across such a situation when I am not able to decide which join will be suitable, a left or right.
Here is the query where I am stuck.
SELECT count(ImageId) as [IndividualRemaining],
userMaster.empName AS ID#,
CONVERT(DATETIME, folderDetails.folderName, 101) AS FolderDate,
batchDetails.batchName AS Batch#,
Client=#ClientName,
TotalInloaded = IsNull(#TotalInloaded,0),
PendingUnassigned = #PendingUnassigned,
InloadedAssigned = IsNull(#TotalAssigned,0),
TotalProcessed = #TotalProcessed,
Remaining = #Remaining
FROM
batchDetails
Left JOIN folderDetails ON batchDetails.folderId = folderDetails.folderId
Left JOIN imageDetails ON batchDetails.batchId = imageDetails.batchId
Left JOIN userMaster ON imageDetails.assignedToUser = userMaster.userId
WHERE folderDetails.ClientId =#ClientID and verifyflag='n'
and folderDetails.FolderName IN (SELECT convert(VARCHAR,Value) FROM dbo.Split(#Output,','))
and userMaster.empName <> 'unused'
GROUP BY userMaster.empName, folderDetails.folderName, batchDetails.batchName
Order BY folderDetails.Foldername asc
Yes, it depends on the situation you are in.
Why use SQL JOIN?
Answer: Use the SQL JOIN whenever multiple tables must be accessed through an SQL SELECT statement and no results should be returned if there is not a match between the JOINed tables.
Reading this original article on The Code Project will help you a lot: Visual Representation of SQL Joins.
Also check this post: SQL SERVER – Better Performance – LEFT JOIN or NOT IN?.
Find original one at: Difference between JOIN and OUTER JOIN in MySQL.
In two sets:
Use a full outer join when you want all the results from both sets.
Use an inner join when you want only the results that appear in both
sets.
Use a left outer join when you want all the results from set a, but
if set b has data relevant to some of set a's records, then you also
want to use that data in the same query too.
Please refer to the following image:
I think what you're looking for is to do a LEFT JOIN starting from the main-table to return all records from the main table regardless if they have valid data in the joined ones (as indicated by the top left 2 circles in the graphic)
JOIN's happen in succession, so if you have 4 tables to join, and you always want all the records from your main table, you need to continue LEFT JOIN throughout, for example:
SELECT * FROM main_table
LEFT JOIN sub_table ON main_table.ID = sub_table.main_table_ID
LEFT JOIN sub_sub_table on main_table.ID = sub_sub_table.main_table_ID
If you INNER JOIN the sub_sub_table, it will immediately shrink your result set down even if you did a LEFT JOIN on the sub_table.
Remember, when doing LEFT JOIN, you need to account for NULL values being returned. Because if no record can be joined with the main_table, a LEFT JOIN forces that field to appear regardless and will contain a NULL. INNER JOIN will obviously just "throw away" the row instead because there's no valid link between the two (no corresponding record based on the ID's you've joined)
However, you mention you have a where statement that filters out the rows you're looking for, so your question on the JOIN's are null & void because that is not your real problem. (This is if I understand your comments correctly)