simple order by clause not working with inner join - php

this query is simply not ordering results the way i want it to:
$sql = mysql_query("select s.*, p.label, p.number
from `sales` as s
left join `pumps` as p on (p.id = s.id_pump)
where s.the_date >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 DAY))
order by CAST(s.amount_sale AS int) desc
limit 1") or die(mysql_error());
i am getting a mysql error.

Try casting the VARCHAR to a signed integer:
$sql = mysql_query("select s.*, p.label, p.number
from `sales` as s
left join `pumps` as p on (p.id = s.id_pump)
where s.the_date >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 DAY))
order by CAST(s.amount_sale AS SIGNED) desc
limit 1");

Related

Get SUM in related table. If not found get 0 as sum

I have this query:
$sql = "SELECT m.id FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND
MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
LEFT JOIN transactions t ON t.user_id = o.user_id";
I need to get sum of transactions.points, so I do this:
$sql = "SELECT m.id, COALESCE(SUM(t.points), 0) AS total_points FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND
MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
LEFT JOIN transactions t ON t.user_id = o.user_id";
But when i execute this, I will get only rows with some transactions (and orders). What I must to do for getting 0 as total_points when no transactions found?
Text description: I want to get sum of points reward (from transactions table) of orders (orders table), where order was created in last month.
Thanks!
Get the sum of points per user and use it in the left join to get 0 when the user has no transactions.
SELECT m.id, COALESCE(t.total_points, 0) AS total_points
FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
/* use this instead of functions which prevent indexes on the date column from being used */
o.date >= date '2016-11-01' AND o.date <= date '2016-11-30'
LEFT JOIN (select user_id, SUM(points) total_points
from transactions group by user_id) t ON t.user_id = o.user_id
You need to add a GROUP BY clause to your query without which you are actually performing SUM() on the entire resultset. Not sure on which column but say on m.id
$sql = "SELECT m.id, COALESCE(SUM(t.points), 0) AS total_points FROM members m
LEFT JOIN orders o ON o.user_id = m.id AND
YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND
MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
LEFT JOIN transactions t ON t.user_id = o.user_id
GROUP BY m.id";

Select with inner join

i need select some data from two tables ,
please help me use inner join for this selection .
players in selction2 must not be in selection1...
first select :
$rs = "SELECT *
FROM `player`
WHERE `status`=1 AND `credit`>=1 AND `username` NOT LIKE '$user'
ORDER BY ls ASC,credit DESC
LIMIT 0 ,10;
Second: this players must remove from result of selection1
$rs2 = "SELECT *
FROM `ip_log`
WHERE `playerid`='$ui' AND `win`='1' AND `date`='$date' ";`
You can use LEFT JOIN for this:
This shows the log messages for everyone not in selection 1.
SELECT l.*
FROM ip_log AS l
LEFT JOIN
(SELECT username
FROM player
WHERE status = 1 AND credit >= 1 AND username NOT LIKE '$user'
ORDER BY ls ASC, credit DESC
LIMIT 10) AS p
ON l.player = p.username
WHERE win = 1 and date = '$date'
AND p.username IS NULL
This shows the top 10 player data, except the ones with log messages in selection 2
SELECT p.*
FROM player AS p
LEFT JOIN ip_log AS l ON l.player = p.username AND l.win = 1 AND l.date = '$date'
WHERE p.status = 1 AND p.credit >= 1 AND p.username NOT LIKE '$user'
AND l.player IS NULL
ORDER BY p.ls ASC, p.credit DESC
LIMIT 10
In both cases, testing a column in the second table with IS NULL makes it return only the rows in the first table that don't have a match in the second table. See
Return row only if value doesn't exist
You can do it with LEFT JOIN
SELECT player.*,ip_log.* FROM `player` LEFT JOIN `ip_log` ON player.id!=ip_log.playerid GROUP BY player.id

MySQL Query - alternative

My query is too long (3-4s). Any idea's how make this faster?
SELECT u.id AS id_uzytkownika,
u.login,
u.ranga,
u.online_light AS online,
(SELECT MAX(id)
FROM uzytkownicy_zdjecia
WHERE id_uzytkownika = u.id
AND prywatna =0) AS id_fotki,
(SELECT fotka
FROM uzytkownicy_zdjecia
WHERE id = id_fotki) AS fotka ,
(SELECT srednia_ocen
FROM uzytkownicy_zdjecia
WHERE id = id_fotki) AS srednia_ocen,
(SELECT ile_ocen
FROM uzytkownicy_zdjecia
WHERE id = id_fotki) AS ile_ocen
FROM uzytkownicy u
WHERE u.foto =1
AND u.plec = "mezczyzna"
ORDER BY srednia_ocen DESC,
ile_ocen DESC,
id_fotki DESC LIMIT 42
Could you maybe explain your table structure and what this query is about? Since the column names are not in English, most readers will probably have a problem understanding what you are trying to do here...
In general, it looks like you have a LOT of nested SELECTS here to the same table - is there any special reason for that?
Try this:
SELECT u.id AS id_uzytkownika,
u.login,
u.ranga,
u.online_light AS online,
(SELECT MAX(id)
FROM uzytkownicy_zdjecia
WHERE id_uzytkownika = u.id
AND prywatna =0) AS id_fotki,
z.fotka,
z.srednia_ocen,
z.ile_ocen
FROM uzytkownicy u
JOIN uzytkownicy_zdjecia z
ON u.id_fotki = z.id
WHERE u.foto =1
AND u.plec = "mezczyzna"
ORDER BY srednia_ocen DESC,
ile_ocen DESC,
id_fotki DESC LIMIT 42
I've substituted 3 subqueries with a JOIN. The first subquery has a different condition, if you can merge that condition withn others queries you can remove that.
Pay attention You have named id_fokta the result of subquery, but the same name has the primary key of uzytkownicy table
You don't have to query the same table with the same criteria again and again. Replace your sub-selects with a simple join. A LEFT JOIN, if it is possible that no matching record exists.
SELECT
u.id AS id_uzytkownika,
u.login,
u.ranga,
u.online_light AS online,
(
SELECT MAX(id)
FROM uzytkownicy_zdjecia
WHERE id_uzytkownika = u.id
AND prywatna =0
) AS id_fotki,
uz.fotka,
uz.srednia_ocen,
uz.ile_ocen
FROM uzytkownicy u
LEFT JOIN uzytkownicy_zdjecia uz ON uz.id = u.id_fotki
WHERE u.foto = 1
AND u.plec = "mezczyzna"
ORDER BY u.srednia_ocen DESC,
u.ile_ocen DESC,
u.id_fotki DESC LIMIT 42
An alternative way to write the query above is to aggregate first and then join:
SELECT
u.id AS id_uzytkownika,
u.login,
u.ranga,
u.online_light AS online,
uzz.id_fotki,
uz.fotka,
uz.srednia_ocen,
uz.ile_ocen
FROM uzytkownicy u
LEFT JOIN uzytkownicy_zdjecia uz ON uz.id = u.id_fotki
LEFT JOIN
(
SELECT id_uzytkownika, MAX(id) AS id_fotki
FROM uzytkownicy_zdjecia
WHERE prywatna =0
GROUP BY id_uzytkownika
) uzz ON uzz.id_uzytkownika = u.id
WHERE u.foto = 1
AND u.plec = "mezczyzna"
ORDER BY u.srednia_ocen DESC,
u.ile_ocen DESC,
u.id_fotki DESC LIMIT 42
By the way: What is "mezczyzna"? A string? Then this should be single quotes.

Use of COUNT twice in PHP MySQL Left Join

I have the following COUNT functionality working successfully in this query. I'd like to issue the exact same COUNT/Left Join functionality on another table (same format) called HTG_ScheduledActual
This works:
$query_WADAHTG_TechProps = "SELECT
HTG_TechProps.EmpNumber, HTG_TechProps.EmpFirstName, HTG_TechProps.EmpLastName, HTG_TechProps.Veh_Number,
COUNT(HTG_ScheduleRequest.ID) AS current_job FROM HTG_TechProps
LEFT JOIN HTG_ScheduleRequest ON HTG_TechProps.EmpNumber = HTG_ScheduleRequest.SSR
AND (HTG_ScheduleRequest.ScheduleDateOriginal = CURDATE()
OR HTG_ScheduleRequest.ScheduleDateCurrent = CURDATE()
OR HTG_ScheduleRequest.ScheduleDateExact = CURDATE() ) GROUP BY HTG_TechProps.EmpNumber
ORDER BY HTG_TechProps.EmpNumber ASC
";
I try to insert a second COUNT using AND and it breaks the query. I have bad feeling I can't issue two COUNT in the same query? How is the best way to overcome this?
$query_WADAHTG_TechProps = "SELECT
HTG_TechProps.EmpNumber, HTG_TechProps.EmpFirstName, HTG_TechProps.EmpLastName, HTG_TechProps.Veh_Number,
COUNT(HTG_ScheduleRequest.ID) AS current_job FROM HTG_TechProps
LEFT JOIN HTG_ScheduleRequest ON HTG_TechProps.EmpNumber = HTG_ScheduleRequest.SSR
AND (HTG_ScheduleRequest.ScheduleDateOriginal = CURDATE()
OR HTG_ScheduleRequest.ScheduleDateCurrent = CURDATE()
OR HTG_ScheduleRequest.ScheduleDateExact = CURDATE() ) GROUP BY HTG_TechProps.EmpNumber
AND COUNT(HTG_ScheduleActual.ID) AS actual_job FROM HTG_TechProps
LEFT JOIN HTG_ScheduleActual ON HTG_TechProps.EmpNumber = HTG_ScheduleActual.SSR
AND (HTG_ScheduleActual.ScheduleDateOriginal = CURDATE()
OR HTG_ScheduleActual.ScheduleDateCurrent = CURDATE()
OR HTG_ScheduleActual.ScheduleDateExact = CURDATE() ) GROUP BY HTG_TechProps.EmpNumber
ORDER BY HTG_TechProps.EmpNumber ASC
";

adding DATE_SUB to query to return range of values in mysql

Here is my original query:
$query = mysql_query("SELECT s.*, UNIX_TIMESTAMP(`date`) AS `date`, f.userid as favoritehash FROM songs s LEFT JOIN favorites f ON f.favorite = s.id AND f.userid = '$userhash' ORDER BY s.date DESC");
This returns all the songs in my DB and then joins data from my favorites table so I can display wich items a return visitors has clicked as favorites or not. Visitors are recognized by a unique has storred in a cookie and in the favorites table.
I need to alter this query so that I can get just the last months worth of songs. Below is my attempt at adding DATE_SUB to my query:
$query = mysql_query("SELECT s.*, UNIX_TIMESTAMP(`date`) AS `date`, f.userid as favoritehash FROM songs s WHERE `date` >= DATE_SUB( NOW( ) , INTERVAL 1 MONTH ) LEFT JOIN favorites f ON f.favorite = s.id AND f.userid = '$userhash' ORDER BY s.date DESC");
Suggestions?
You just have to move the WHERE clause:
SELECT
s.*,
UNIX_TIMESTAMP(`date`) AS `date`,
f.userid as favoritehash
FROM
songs s
LEFT JOIN favorites f ON f.favorite = s.id AND f.userid = '$userhash'
WHERE `date` >= DATE_SUB( NOW( ) , INTERVAL 1 MONTH )
ORDER BY s.date DESC
LEFT JOIN is a part of the list of tables in FROM, you can't have conditions where.

Categories