How delete children and still display parents with PHP and SQL [duplicate] - php

I have a table cars(id, name) containing 20 rows. The other table carLog(username, car, count) contains rows which count the cars a player has bought (if there is no row if they haven't bought the car)
I want my query to return all twenty cars, and the extra join info, if they've got a row in the carLog table but I can't get it to work.
SELECT * FROM cars LEFT JOIN carLog ON cars.id=carLog.car
This is returning hundreds of rows, I want it to return 20 rows (one for each car), and the extra info in the row if the username has purchased the car:
WHERE carLog.username='Juddling'
I have no idea if I'm meant to be using GROUP BY, WHERE or another type of join!

Move the username condition from the WHERE clause to the ON clause.
SELECT *
FROM cars
LEFT JOIN carLog
ON cars.id=carLog.car
AND carLog.username='Juddling'
The WHERE clause is applied when the JOIN is already completed. This means, it will discard the NULL rows that the LEFT JOIN added.

As you are limiting the table from the outer join, you have to put the condition in the on, not the where:
select * from cars
left join carLog on cars.id = carLog.car and carlog.username = 'Juddling'

Related

Mysql - Verify if part of a result exists in another table

I have two tables in Mysql, one is all the data I need to display to users and in another simply a list of URLs of the items that were deleted.
What I want to do is select all the results as long as the element does not exist in the "deleted items" table.
In my table of "Deleted_Items" I have a list of URLs of the type
https://example.com/video/123456/
But in my table "Items" the URL column contains the following:
https://example.com/video/123456/dogs_and_cats/
I would need to do something like this (pseudocode):
SELECT id, url, thumb FROM Items
WHERE Items.url NOT CONTAINS Deleted_Items.url
P.S:
I had a similar case with two other tables but the difference was that in the "Items" table I had a list of IDs and in the "Deleted_Items" table I also had a list of IDs, so I applied the following query:
SELECT id, url, thumb
FROM Items
LEFT OUTER JOIN Deleted_Items
ON (Items.url = Deleted_Items.url)
WHERE Deleted_Items.url IS NULL
LIMIT 30
You could use a left join check for deleted_item.url is null
SELECT Items.id, Items.url, .Itemsthumb
FROM Items
LEFT JOIN deleted_Items ON Items.url = deleted_Items.url
where deleted_Items.url is null
looking to your added data sample could be you need a like comparision
SELECT Items.id, Items.url, .Itemsthumb
FROM Items
LEFT JOIN deleted_Items ON deleted_Items.url like concat(Items.url , '%')
where deleted_Items.url is null

How to show data from two table order by average of second table

I have two tables in MYSQL database with the following attributes.
services(id,name,details).
rating(id,sid,points).
In the rating table sid is foreign key of service table.
I want to show data in the following format
output(service id, name, details,average points) order by average points.
I have used the following query for this purpose
SELECT s.*, ROUND(COALESCE(AVG(r.points),0)) AS rating
FROM services s, rating r
WHERE s.id=r.sid
ORDER BY rating DESC
Above query shows the result only when record exists in the rating table. I want to show the both records who's record exists or not in the rating table. if there is no record in the rating table than its average will be counted as zero.
Please help me.
Change the implicit join to a left outer join (which will return null) and wrap the avg in an ifnull
SELECT s.*, ifnull(ROUND(COALESCE(AVG(r.points),0)),0) AS rating
FROM services s
left outer join rating r on s.id=r.sid
ORDER BY rating DESC

MySQL Join - Sorting data, grouping data

I have two tables:
twitterusers table
twittergrowth Table
I am trying to do JOIN these 2 tables, get all fields from twitteruser and selective fields from twittergrowth, then fetch only the last 3 rows from this data.
Expected Output:
Current Output:
I.e the rows are repeating. I want rows unique by ID or usernames, and the last set of timestamps. So it would be the last 3 rows, which has the most recent timestamps.
The code I could type scribble out is :
SELECT
t1.*,
t2.new_followers_count,
t2.new_friends_count,
t2.new_timestamp
FROM twitterusers t1
JOIN twittergrowth t2 on (t1.username=t2.username)
Searched quite few pages/sites, but cant really figure out how to do it. I would appreciate any help. :)
Additionally, I would like to get a LIMIT parameter added to the final result, so that I can paginate the full result.
First you need to find a maximum new_timestamp (latest) within groups of the same user_id and username in twittergrowth table. This is a classic group-wise maximum problem and the subquery tgmax does that. Then you need to join back the same table (tg this time) to get other columns that aren't in the group by clause of subquery and are not used in aggregate functions (like max()). These columns are new_followers_count and new_friends_count.
If you tried to put them in the select of subquery mysql would return values from an unspecified row from the same group and not necessarily the same as the one with the latest timestamp. This is explained here.
Once you get desired output for twittergrowth table the only thing left is to join twitterusers table to get all other columns.
SELECT tu.*, tg.new_followers_count, tg.new_friends_count, tg.new_timestamp
FROM twitterusers tu
JOIN twittergrowth tg
ON tu.user_id = tg.user_id AND tu.username = tg.username
JOIN
( SELECT tgg.user_id, tgg.username, max(tgg.new_timestamp) as latest_timestamp
FROM twittergrowth tgg
GROUP BY tgg.user_id, tgg.username ) tgmax
ON tg.user_id = tgmax.user_id AND tg.username = tgmax.username
AND tg.new_timestamp = tgmax.latest_timestamp
Note that this query would benefit from a composite index on (user_id,username,new_timestamp) in the twittergrowth table.
You need to group by to achieve your expected output.
GROUP BY id
To limit, or split results into pages, you can simply add LIMIT X,Y where X is the starting record and Y is the total number of records.
So a query to pull the expected results you want, but only the first 10 would be like so:
SELECT
t1.*,
t2.new_followers_count,
t2.new_friends_count,
t2.new_timestamp
FROM twitterusers t1
JOIN twittergrowth t2 on t1.username=t2.username
GROUP BY t1.id
LIMIT 0,10

php and mysql queries

I'm creating a website where the user can add some information about multiple computers into a database.
In the mysql database I have 3 tables. TypeOfMachine, Software and Hardware. The only common thing they have is the NumberOfMachine.
I must create a page where the user can run reports showing devices that have a specific piece of software installed (user specified) or specific hardware (user specified) after he submitted the computer's info.
Any ideas how I can do this?
And how I can connect all 3 tables into one?
I thought about this code but i dont know what to put in WHERE. I have 10 variables. and I have to show all the computers with what the user has asked and their info as well!
$search1 = "
SELECT
TypeOfMachine.NumberOfMachine, TypeOfMachine.TypeOfMachine, TypeOfMachine.OS, Software.Software1, Software.Software2, Software.Software3, Hardware.SSD, Hardware.Harddisk, Hardware.MonitorSize, Hardware.Ram, Hardware.Rom, Hardware.Processor
FROM TypeOfMachine, Software, Hardware
WHERE
but i
You want to use a join. This example is based on the fact that you've said the NumberOfMachine field is present in all tables and is a common link between them:
SELECT
TypeOfMachine.NumberOfMachine,
TypeOfMachine.TypeOfMachine,
TypeOfMachine.OS,
Software.Software1,
Software.Software2,
Software.Software3,
Hardware.SSD,
Hardware.Harddisk,
Hardware.MonitorSize,
Hardware.Ram,
Hardware.Rom,
Hardware.Processor
FROM TypeOfMachine
LEFT JOIN Software
ON Software.NumberOfMachine = TypeOfMachine.NumberOfMachine
LEFT JOIN Hardware
ON Hardware.NumberOfMachine = TypeOfMachine.NumberOfMachine
WHERE
...
It's general question, I don't know which tables contains a spesific columns as indicator for all tables. It's about inner and outer join:
The two common types of joins are an inner join and an outer join. The difference between an inner and outer join is in the number of rows included in the results table.
Inner join: The results table produced by an inner join contains only rows that existed in both tables.
Outer join: The combined table produced by an outer join contains all rows that existed in one table with blanks in the columns for the rows that did not exist in the second table.
For instance, if table1 contains a row for Joe and a row for Sally, and table2 contains only a row for Sally, an inner join would contain only one row: the row for Sally. However, an outer join would contain two rows — a row for Joe and a row for Sally — even though the row for Joe would have a blank field for weight.
The results table for the outer join contains all the rows for one table. If any of the rows for that table don’t exist in the second table, the columns for the second table are empty. Clearly, the contents of the results table are determined by which table contributes all its rows, requiring the second table to match it.
Two kinds of outer joins control which table sets the rows and which must match: a LEFT JOIN and a RIGHT JOIN.
You use different SELECT queries for an inner join and the two types of outer joins. The following query is an inner join:
SELECT columnnamelist FROM table1,table2
WHERE table1.col2 = table2.col2
And these queries are outer joins:
SELECT columnnamelist FROM table1 LEFT JOIN table2
ON table1.col1=table2.col2
SELECT columnnamelist FROM table1 RIGHT JOIN table2
ON table1.col1=table2.col2
In all three queries, table1 and table2 are the tables to be joined. You can join more than two tables. In both queries, col1 and col2 are the names of the columns being matched to join the tables. The tables are matched based on the data in these columns. These two columns can have the same name or different names, but they must contain the same type of data.
For general concept you can use #Scrowler suggestion, or this one:
http://stackoverflow.com/questions/1204217/mysql-select-join-3-tables

Tricky MySQL query involving NOT IN

I have two tables that I am joining together in order to get results.
One table contains a list of assessments with a unique ID (assessments), whilst the other table (staff_to_assessments) contains a list of assessments that are assigned to staff members. An example record for this table would contain the Staff member unique ID, and the assignment unique ID. This shows that a user has been linked to an assignment.
I have written a function which only grabs assessments from the assessment table where they have not been assigned to a staff member in staff_to_assessment table. This is to populate a drop-down box on the front end where these remaining assessments can be assigned to a staff member if required, therefore I don;t want to show any that are already assigned.
MySQL query is as follows:
SELECT * FROM assessments a
LEFT JOIN staff_to_assessment s2a ON a.assessment_id = s2a.assessment_id
WHERE a.assessment_id NOT IN
(SELECT assessment_id FROM staff_to_assessment WHERE staff_id = '" . (int)$options['staffId'] . "')";
This doesn't seem to generate the response I need. Can anybody see where I have gone wrong?
Thanks!!
I think your query is working too hard. You just need to find rows where there is no match to the left outer join:
SELECT a.*
FROM assessments a LEFT JOIN
staff_to_assessment s2a
ON a.assessment_id = s2a.assessment_id
WHERE s2a.assessment_id is null;
You don't need to use both a left join and a not in clause.
Queries like NOT IN [subquery] can (and should) always be rewritten as a LEFT JOIN.
SELECT a.*
FROM assessments a
LEFT JOIN staff_to_assessment s2a USING (assessment_id) -- equivalent to "ON a.assessment_id = s2a.assessment_id", as both columns have the same name
WHERE staff_id IS NULL
This is equivalent to:
SELECT a.*
FROM assessments a
WHERE a.assessment_id NOT IN (SELECT assessment_id FROM staff_to_assessment)
Both are usually optimised away to the same execution plan, but the former is preferable as it tends to produce quicker queries.

Categories