LEFT JOIN not showing NULL results - php

I have 2 tables:
DAY_INTERVALS (interval_start)
ORDERS (client_id, order_time, order_total_price)
I want to display all the days in the DAY_INTERVAL table against the ORDERS table. Below is the SQL that I am using.
SELECT DATE_FORMAT(order_time,'%Y-%m-%d') as dates, COALESCE(SUM(order_total_price), 0) AS sales
FROM time_intervals ti
LEFT JOIN orders o
ON DATE(o.order_time) = ti.interval_start AND (o.client_id = 157 or o.client_id is NULL)
GROUP BY DAY(o.order_time)
It is not displaying the NULL results of the days which don't exist in the orders table. The query should display all the days regardless if it is in the orders table.
I have looked at similar questions but the query above is what I come up with based on the other solutions.
Any advise would be much appreciated.

If you get rid of AND (o.client_id = 157 or o.client_id is NULL) it would give you the data set you're looking for.
You're effectively executing the "Left Excluding JOIN" from this article:
http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
The only difference is you're executing it from your ON clause instead of the WHERE clause.

Related

PHP/MySQL Duplicate values from select

I am running this query
$sql6 = "SELECT RECIPE.Price, RECIPE.Name FROM ORDERRECI, ORDERS, RECIPE WHERE ORDERRECI.OrderID = $orderID AND ORDERRECI.RecipeID = RECIPE.RecipeID";
$results = mysqli_query($con, $sql6);
while ($row=mysqli_fetch_assoc($results))
{
$calcC+= $row['Price'];
echo $calcC.$row['Name']."<br />";
}
return $calcC;
The query Runs fine I'm getting the right values But I'm getting them 9 times.( I checked via the echo). I checked the Database they are only in there once. I tried using Distinct but because the customer can pick the same side multiple times they would get an inaccurate result (tested. Can anyone explain why. Would using join help. My teacher favors where(Don't know why) but that's why I use it
EDIT:
I Recipe and Orders have a many-to-many relationship ORDERRECI is the referential table. I am trying to calculate the Total Cost of an order. I just tried inner join but it still duplicated and this time it duplicated 14 times
FROM ORDERRECI, ORDERS, RECIPE here you are doing a Cartesian product with the 3 tables, which means, each row from each table will be paired with each row from every other table from the FROM list. I don't know what was your goal with the query, but that is whats happening.
Try adding this to your query
GROUP BY RECIPE.Name
For each row in ORDERRECI you create a merged row with each one of the rows in ORDERS and the same goes for RECIPE.
You should use LEFT JOIN. Read about SQL join types here
I ended up with this statement. I Needed the general join of the tables. then use where to narrow it down. Thanks for the help in figuring it out
$sql = "SELECT RECIPE.Price FROM ORDERRECI INNER JOIN ORDERS ON ORDERRECI.OrderID = ORDERS.OrderID INNER JOIN RECIPE ON ORDERRECI.RecipeID = RECIPE.RecipeID WHERE ORDERS.OrderID = $orderID";

mysql calculate percentage between two sub queries

I am trying to work out the percentage of a number of students who meet certain criteria.
I have 3 separate tables that I need to get data from, and then I need to get the total from one table (student) as the total of students.
Then I need to use this total, to divide the COUNT of the no of students in the 2nd query.
So basically I am trying to get a count of ALL the students that are in the DB first.
Then count the no of students that appear in my main query (the one returning the data).
Then I need to perform the calculation that will take the noOfStudents (2) and divide by the main total (24) (no of students in DB) then *100 to give me the percentage of students who have met the criteria in the main query.
This is what I have so far:
SELECT * FROM (
(
SELECT s.firstname, s.lastname, s.RegistrationDate, s.Email, d.ReviewDate,(r.description) AS "Viva" , COUNT(*) AS "No of Students"
FROM student s
INNER JOIN dates d
ON s.id=d.student_identifier
INNER JOIN reviews r
ON d.review_Identifier=r.id
WHERE r.description = "Viva Date"
GROUP BY s.student_identifier
ORDER BY s.student_identifier)
) AS Completed
WHERE Completed.ReviewDate BETWEEN '2012-01-01' AND '2014-12-01'
;
I need to output the fields following the second SELECT and this data in turn will be displayed via PHP/HTML code on a page (the BETWEEN dates will be sent via '%s').
I wondered if I should be using 2 separate queries and then getting the value (24) from the first query to perform the calculation in the second query, but I have not been able to work out how to save as 2 separate queries and then reference the first query.
I am also not sure if it is possible to display an overall % total at the same time as outputting the individual rows that meet the criteria?
I am trying to teach myself SQL, so I apologise if I have made any glaring mistakes/assumptions in any of the above, and would appreciate any advice that's out there.
Thank you.
Could you do this?
SELECT COUNT(*) as TotalPopulation,
COUNT(d.student_identifier='student') as TotalStudents,
COUNT(d.student_identifier='student')/ count(*) *100 as Percentage of students
from students s
inner join dates d
on s.id = d.student_identifier
inner join reviews r
on r.id = d.review_Identifier
WHERE d.ReviewDate BETWEEN '2012-01-01' AND '2014-12-01' and r.description = 'Viva Date';
You do not need first name last name if you are just looking for counts, necessarily.
This get's the count(*) of table, then whatever flag you use to identify a student in the second count(), you just had it grouped by before, which could give you wrong results considering there's much else in your select before aggregation.
You could also try:
SELECT d.student_identifier, s.firstname, s.lastname,
s.RegistrationDate, s.Email, d.ReviewDate,(r.description) AS "Viva"
FROM student s
INNER JOIN dates d
ON s.id=d.student_identifier
INNER JOIN reviews r
ON d.review_Identifier=r.id
WHERE r.description = "Viva Date" and d.ReviewDate BETWEEN '2012-01-01' AND '2014-12-01'
ORDER BY s.student_identifier
Now, if you want to return a list, that's the second one, if you want to return a count, you would use the first query and adjust to your student_identifier.

How to select from / join 5 tables using PHP and mySQL

I'm trying to build a review record based on fields from 5 tables:
I've marked all the columns I need, but for the moment I'm just retrieving all of the user_rating table.
Here's what I have so far:
SELECT DISTINCT user_rating.*, whiskey.name, user_notes.overall, users.image, user_rate.rate_number
FROM user_rating
LEFT JOIN whiskey ON whiskey.id = user_rating.whiskeyid
LEFT JOIN users ON users.username = user_rating.username
LEFT JOIN user_notes ON user_notes.username = user_rating.username AND user_rating.whiskeyid = user_notes.whiskey_id
LEFT JOIN user_rate ON user_rate.whiskey_id = user_rating.whiskeyid AND user_rate.username = user_rating.username
ORDER BY user_rating.id DESC
At first I thought this was giving me the results I wanted but then I noticed I was getting multiple rows as well as too many null fields. Any help would be greatly appreciated.
Edit:
By multiple rows I mean duplicate rows. Also, I am aware that a left join produces null values on the right side of the join. What I meant to say is that I'm getting more null values than I should be as the data is within the database.
To clarify, I'm trying to create a list of recent reviews with the most recent listed first. Each review consists of a username, 11 categories (each one is an integer value), overall rating (int value), notes (string), image (URL), and whiskey name (string).
1) You can't be getting multiple SAME rows, since you use DISTINCT. (by multiple do you mean duplicate?)
2) You get null fields because you are using LEFT JOIN and your tables cannot be joined (some "ON clause" cannot be evaluated as true)
It turns out that there was nothing wrong with my query. The person whose database I'm using isn't maintaining it so there are several reviews for the same product and user where only the overall rating is different. Also, there are many reviews on products that don't even exist. I should've looked at the database closer to begin with as deleting all of the erroneous rows solved my problem. Thanks for all the input.

Multiple joins in a MySQL query giving incorrect results

I've got a large mysql query with 5 joins which may not seem efficient but I'm struggling to find a different solution which would work.
The views table is the main table here, because both clicks and conversions table rely on it via the token column(which is indexed and set as a foreign key in all tables).
The query:
SELECT
var.id,
var.disabled,
var.name,
var.updated,
var.cid,
var.outdated,
IF(var.type <> 0,'DL','LP') AS `type`,
COUNT(DISTINCT v.id) AS `views`,
COUNT(DISTINCT c.id) AS `clicks`,
COUNT(DISTINCT co.id) AS `conversions`,
SUM(tc.cost) AS `cost`,
SUM(cp.value) AS `revenue`
FROM variants AS var
LEFT JOIN views AS v ON v.vid = var.id
LEFT JOIN traffic_cost AS tc ON tc.id = v.source
LEFT JOIN clicks AS c ON c.token = v.token
LEFT JOIN conversions AS co ON co.token = v.token
LEFT JOIN c_profiles AS cp ON cp.id = co.profile
WHERE var.cid = 28
GROUP BY var.id
The results I'm getting are:
The problem is the revenue and cost results are too hight, because for views,clicks and impressions only the distinct rows are counted, but for revenue and cost for some reason(I would really appreciate an explanation here) all rows in all tables are taken into the result set.
I know this is a large query, but both clicks and conversions tables rely on the views table which is used for filtering the results e.g. views.country = 'uk'. I've tried doing 3 queries and merging them, but that didn't work(it gave me wrong results).
One more thing that I find weird is that if I remove the joins with clicks, conversions, c_profiles the costs column shows correct results.
Any help would be appreciated.
In the end I had to use 3 different queries and do a merge on them. Seemed like an overhead, but worked for me.

Complex SQL Query Help

Given a pretty standard set of related tables like Customers, Invoices and Line Items. I need to make a query like "Select all customers that have invoices that have 5 line items or more" or "Select all customers that have more than 2 invoices" or lastly "Select all customers that have line items totaling more than $100"
I'm doing this the hard way now (walking through all the records manually) and I know it's the most inefficient way but I don't know enough SQL to construct these queries. I'm using PHP5, MySQL and CakePHP 1.25.
Start by joining them all together:
select c.id
from customers c
left join invoices i on i.customer_id = c.id
left join lineitems li on li.invoice_id = i.id
group by c.id
To filter customers with more than 5 line items or more, add:
having count(li.id) >= 5
Filtering customers with two or more invoices is trickier, since we're joining the lineitems table. There may be multiple rows per invoice. So to count only unique invoices, we have to add distinct to the count, like:
having count(distinct i.id) >= 2
To filter customers with more than $100 in items, add:
having sum(li.cost) > 100
You can use math inside the sum, in case you're storing separate line item counts and prices:
having sum(li.itemcount * li.itemcost) > 100
For the first two you can use GROUP BY and HAVING COUNT(*)>4 and for the last one you can use SUM(field).
If you want SQL then please show your attempt.
Say you had:
customers.id
line_items.user_id
line_items.numItems
Query would look like:
SELECT * FROM customers
JOIN line_items
ON line_items.user_id WHERE line_items.numItems > 5
Your WHERE clause will change depending on what you wanted to return.
Haven't worked with SQL Joins in a while, but I think it's something like that.
Here is some help with the second one that should get you going:
SELECT customer_id, COUNT(*) AS num_invoices
FROM invoices
GROUP BY customer_id
HAVING COUNT(*) > 2

Categories