LEFT JOIN query MYSQL does not work - mysql

I have 2 tables rtz_order and rtz_restaurant
From order I want purchaseprice from restaurant i want "restaurant_commission" both have a column called restaurant_id So i want to join these to tables and add the restaurant_commission tot the query. I have come up with this (the date part etc works, i was already using that but the query does not work since I added the join)
$sql = 'SELECT
order.orderpurchase,
order.orderdate,
order.status,
order.restaurant_id,
res.restaurant_commission,
res.restaurant_id
FROM rt_order order
LEFT JOIN rt_restaurant res ON order.restaurant_id = res.restaurant_id
WHERE date(order.orderdate) >= date(?) AND date(order.orderdate) <= date(?)
AND order.restaurant_id = ? AND order.status = "completed"';
I have tried diffrent things but i do not see why this is going wrong

ORDER is a reserved keyword.
Use backtics like:
`ORDER`
Check the complete list of reserved keywords here.
NOTE : It is better to avoid reserved keywords for column names, but if you use then wrap them with backtics.

Your alias order is a MySQL reserved word.
Make it either `order` using backticks, or change the alias' name.

Related

MySQL join with conditional "on" statement

Say I have the below 2 tables:
text
id
text_lang
id
media_id
lang
text
(these are not the actual table structures - but I just have 2 tables with one containing all the localized strings that "belong" to the first table)
I want to join the tables, with a "preferred" language. So basically:
SELECT text.id, text_lang.text
FROM text
LEFT JOIN text_lang ON text.id = text_lang.text_id
AND (only a single row, and if there's a row with lang="en", pick that,
otherwise just pick any language)
The part I'm having trouble with is the "only a single row, and if there's a row with lang="en" pick that, otherwise just pick any language".
I think this does what I'm looking for:
SELECT text.id, text_lang.text
FROM text
JOIN text_lang ON text_lang.text_id = text.id AND
text_lang.lang = (select lang
FROM text_lang sub_text_lang
WHERE sub_text_lang.text_id = text.id
ORDER BY text_lang.lang = "en" DESC
limit 1)
... but I'd like to avoid a sub-query if possible, as I assume that would be quite a hit to the query performance.
I can think of a few ways but since you're trying to avoid subquery, perhaps you can do something like this:
SELECT t.id,
SUBSTRING_INDEX(
GROUP_CONCAT(text ORDER BY CASE WHEN lang='en' THEN 0 ELSE RAND() END),',',1)
AS extracted_text
FROM
text t
LEFT JOIN text_lang tl ON tl.text_id=t.id
GROUP BY t.id;
Use GROUP_CONCAT() with a customized ORDER BY then use SUBTRING_INDEX() to get the first value using comma (the default GROUP_CONCAT() separator) as the delimiter.
I've made a fiddle with sample data here: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0d0501f36af1ba4e181856f761dbd5f7 . You can run the fiddle a few times to see that the text value other than 'en' change.

Increase performance query when use CONCAT in where clause

My query is:
SELECT *
FROM user u
LEFT JOIN user_detail ud ON u.id = ud.user_id
WHERE CONCAT(ud.first_name,' ',ud.last_name) LIKE 'John Smith%'
I created two index on first_name and last_name column, but I know they didn't work when use CONCAT in where clause because CONCAT scans full table.
Suppose I can't change table to create a new column as full_name. Is there anyway to increase performance in this case?
Noted:
Because the input can be any text such as first name, last name or full name so I use CONCAT and the full query is :
SELECT *
FROM user u
LEFT JOIN user_detail ud ON u.id = ud.user_id
WHERE (CONCAT(ud.first_name,' ',ud.last_name) LIKE 'search%') OR (CONCAT(ud.last_name,' ',ud.first_name) LIKE 'search%')
If your intention is to always use concat, then just create function index rather then indexing to separate columns
CREATE INDEX idx1 ON user_Details (CONCAT(ud.first_name,' ',ud.last_name));
otherwise I suggest you splitting rather than concatenation
WHERE ud.first_name = '?' AND ud.last_name LIKE '?%'
You tried if it is faster with :
ud.first_name = 'John' AND d.last_name like 'Smith%'
The comparison on the first string already may abort and equals is faster than like.
see also: Use '=' or LIKE to compare strings in SQL?

MAX(Date) is giving empty result

I have a table with exchange rate like below
And I am using the maxofdate to pick all these values based on currency code. But the query is giving blank.
Select USDAMOUNT * dbo.EXCHANGERATEAMT
from dbo.Amount_monthly
Left Join dbo.EXCHANGERATE on dbo.Amount_monthly.Currencycode=dbo.EXCHANGERATE.fromcurrencycode
WHERE ValidToDateTime = (Select MAX(ValidToDateTime) from dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY'
Using this statement
CONVERT(DATE,ValidToDateTime) = CONVERT(DATE,GETDATE()-1)
instead of subquery is giving me expected result.
Can someone correct this.
thanks in advance.
If I understand correctly, you need two things. First, the condition for the max() needs to match the condition in the outer query. Second, if you really want a left join, then conditions on the second table need to go in the on clause.
The resulting query looks like:
Select . . .
from dbo.Amount_monthly am Left Join
dbo.EXCHANGERATE er
on am.Currencycode = er.fromcurrencycode and
er.ValidToDateTime = (Select max(er2.ValidToDateTime)
from dbo.EXCHANGERATE er2
where er2.EXCHANGERATETYPECODE = 'DAY'
) and
er.EXCHANGERATETYPECODE = 'DAY';
I would write this using window functions, but that is a separate issue.
Try removing WHERE clause for ValidToDateTime and include it in the JOIN as AND condition
SELECT USDAMOUNT * dbo.EXCHANGERATEAMT
FROM dbo.Amount_monthly
LEFT JOIN dbo.EXCHANGERATE
ON dbo.Amount_monthly.Currencycode = dbo.EXCHANGERATE.fromcurrencycode
AND ValidToDateTime = (SELECT MAX(ValidToDateTime) --remove WHERE clause
FROM dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY';
I cleaned up your query a bit: as the other folks mentioned you needed to close the parentheses around the MAX(Date) sub-query, and if you reference a LEFT JOINed table in the WHERE clause, it behaves like an INNER JOIN, so I changed to in INNER. You also had "dbo" sprinkled in as a field prefix, but that (the namespace) only prefixes a database, not a field. I added the IS NOT NULL check just to avoid SQL giving the "null values were eliminated" SQL warning. I used the aliases "am" for the first table and "er" for the 2nd, which makes it more readable:
SELECT am.USDAMOUNT * er.EXCHANGERATEAMT
FROM dbo.Amount_monthly am
JOIN dbo.EXCHANGERATE er
ON am.Currencycode = er.fromcurrencycode
WHERE er.ValidToDateTime = (SELECT MAX(ValidToDateTime) FROM dbo.EXCHANGERATE WHERE ValidToDateTime IS NOT NULL)
AND er.EXCHANGERATETYPECODE = 'DAY'
If you're paranoid like I am, you might also want to make sure the exchange rate is not zero to avoid a divide-by-zero error.

My SQL JOIN query returning No results

SELECT 'nmc_cd.CDID','nmc_cd.CDTitle', 'nmc_cd.CDYear','nmc_cd.pubID','nmc_cd.catID','nmc_cd.CDPrice','nmc_category.catDesc'
From nmc_cd
JOIN nmc_category
ON 'nmc_cd.catID'='nmc_category.catID'
ORDER BY CDTitle
Ive been putting this query into mySQL to try and get a table with results from ncm_CD and nmc_category but it keeps retuning no value?? also if i use a right or left join it is returning the Column name (e.g. nmc_cd.CDJD)
Try removing the quotes so that you are referencing the column itself - with quotes, you are working with strings and not the columns.
SELECT nmc_cd.CDID, nmc_cd.CDTitle, nmc_cd.CDYear, nmc_cd.pubID, nmc_cd.catID, nmc_cd.CDPrice, nmc_category.catDesc
From nmc_cd
JOIN nmc_category
ON nmc_cd.catID = nmc_category.catID
ORDER BY CDTitle
Also, as #Randy mentions, make sure you actually have data that matches the criteria :)
I am not sure why you have single quotes around everything, a single quote is considered a static string value so it will not return the data from the columns:
SELECT nmc_cd.CDID,
nmc_cd.CDTitle,
nmc_cd.CDYear,
nmc_cd.pubID,
nmc_cd.catID,
nmc_cd.CDPrice,
nmc_category.catDesc
From nmc_cd
INNER JOIN nmc_category
ON nmc_cd.catID=nmc_category.catID
ORDER BY CDTitle
But with the INNER JOIN that you are using you have to be sure that you have values that match data in both tables, if you do not then no data will be returned. If you don't have data in both tables, then you will want to use either a LEFT JOIN or RIGHT JOIN:
SELECT nmc_cd.CDID,
nmc_cd.CDTitle,
nmc_cd.CDYear,
nmc_cd.pubID,
nmc_cd.catID,
nmc_cd.CDPrice,
nmc_category.catDesc
From nmc_cd
LEFT JOIN nmc_category
ON nmc_cd.catID=nmc_category.catID
ORDER BY CDTitle
MySQL uses backticks around columns and table names not single quotes, if you applied them then your query would look like this:
SELECT `nmc_cd`.`CDID`,
`nmc_cd`.`CDTitle`,
`nmc_cd`.`CDYear`,
`nmc_cd`.`pubID`,
`nmc_cd`.`catID`,
`nmc_cd`.`CDPrice`,
`nmc_category`.`catDesc`
From `nmc_cd`
JOIN `nmc_category`
ON `nmc_cd`.`catID`=`nmc_category`.`catID`
ORDER BY `CDTitle`

sql left join for two tables using a CONCAT string as the argument

I need to get a title from table 2, table 2 has title and id column.
Table 1 has some data and three of these columns concatenated together makeup the id that can be found in table 1.
I used CONCAT_WS() function and gave this column an alias name and need to use the Alias for the on argument(At least this is what I understood I needed to do)
I thought this could be a simple left join, yet it is not working for me.
This is my query
SELECT
table_openers.mail,
table_openers.f_name,
table_openers.l_name,
table_openers.Quality,
CONCAT_WS('-',
table_openers.esp,
table_openers.acc,
table_openers.group) as 't1aid',
table_groups.aid,
table_groups.group_name
FROM
lance_mailstats.table_openers
LEFT JOIN
lance_mailstats.table_groups ON table_groups.aid = t1aid;
I get results for mail, f_name, l_name, Quality and t1aid, but the aid and group_name columns of the second table return null.
I feel like you can't use an alias in the ON clause.
Try doing
LEFT JOIN
lance_mailstats.table_groups ON table_groups.aid = CONCAT_WS('-',
table_openers.esp,
table_openers.acc,
table_openers.group);
"You can use the alias in GROUP BY, ORDER BY, or HAVING clauses to refer to the column" (from dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html).
And "The conditional_expr used with ON is any conditional expression of the form that can be used in a WHERE clause" (from dev.mysql.com/doc/refman/5.1/en/join.html).
So as a logical inference you're not allowed to use aliases in ON clauses.
try to use a subquery..
it goes like this.........
ex.
SELECT
tbl1.mail, tbl1.f_name, tbl1.l_name,tbl1.Quality, tbl1.t1aid,table_groups.aid,
table_groups.group_name
FROM
(SELECT
table_openers.mail,
table_openers.f_name,
table_openers.l_name,
table_openers.Quality,
CONCAT_WS('-',
table_openers.esp,
table_openers.acc,
table_openers.group) as 't1aid',
FROM
lance_mailstats.table_openers )tbl1
LEFT JOIN
lance_mailstats.table_groups ON table_groups.aid = tbl1.t1aid;