This question already has answers here:
Operand Should Contain 1 Column - MySQL NOT IN
(3 answers)
Closed 8 years ago.
I have an sql query that was returning some incorrect results due to product id's being duplicated for linked products, so i added the following to the end of my query expecting it to only take the first instance of any product id:
AND pc.products_id
IN
(SELECT
pc.products_id, MIN(categories_id)
FROM
zen_products_to_categories pc
GROUP BY
pc.products_id)
But i get an Operand should contain 1 column(s) error when i run the process. I ran that query on it's own and it only gave me each product id once, so not sure why i get the error.
The full query i now have is:
SELECT p.products_quantity, p.abebooks_status,
p.products_id AS id,
p.products_status AS prodStatus,
FORMAT( IFNULL(s.specials_new_products_price, p.products_price),2) AS price,
pc.categories_id AS prodCatID,
c.parent_id AS catParentID,
cd.categories_name AS catName
FROM
zen_products p
JOIN zen_products_description pd ON p.products_id=pd.products_id
JOIN zen_products_to_categories pc ON p.products_id=pc.products_id
JOIN zen_categories c ON pc.categories_id=c.categories_id
JOIN zen_categories_description cd ON c.categories_id=cd.categories_id
left join zen_specials s on ( s.products_id = p.products_id AND ( (s.expires_date > CURRENT_DATE) OR (s.expires_date = 0) ) )
WHERE p.products_price > 0 and p.products_status = 1
AND pc.products_id
IN
(SELECT pc.products_id, MIN(categories_id)
FROM zen_products_to_categories pc GROUP BY pc.products_id)
ORDER BY catName ASC
Can anyone tell me why it doesn't work when i add the extra query because it's got me baffled
You could try with:
AND (pc.products_id, pc.categories_id)
IN
(SELECT
pc.products_id, MIN(categories_id)
FROM
zen_products_to_categories pc
GROUP BY
pc.products_id)
Edit:
In MySQL a subquery like this is usually slow. You should have better luck with a JOIN:
SELECT ....
FROM
....
INNER JOIN (SELECT
products_id, MIN(categories_id) min_categories_id
FROM
zen_products_to_categories
GROUP BY
products_id) min_ct
ON pc.products_id=min_ct.products_id
AND pc.categories_id=min_ct.min_categories_id
WHERE
....
Subquery should return one column when you are matching against single column remove MIN(categories_id) from your subquery
AND pc.products_id
IN
(SELECT
pc.products_id
FROM
zen_products_to_categories pc
GROUP BY
pc.products_id)
Related
This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 2 years ago.
I'm trying to run a distinct on four columns in the query below:
select
full_records.id,
full_records.domain_id,
subdomains.name as subdomain_name,
types.name as type_name,
changelog.content as content,
changelog.changed_on
from full_records
inner join subdomains on full_records.subdomain_id = subdomains.id
inner join types on full_records.type_id = types.id
inner join changelog on full_records.id = changelog.full_record_id
where
full_records.domain_id = 2
order by changelog.changed_on desc
and this returns the following:
I'm not sure how to go about altering the query so that it only returns the records that are unique across these four fields.
full_records.domain_id,
subdomains.name as subdomain_name,
types.name as type_name,
changelog.content as content
So if they were unique across those four fields, the rows 2, 3, 4 and 7 would not be in the results. It's basically to identify the latest change for a domain record. Any help would be really appreciated. Thanks.
One pretty simple method is row_number():
with cte as (
select fr.id, fr.domain_id, sd.name as subdomain_name,
t.name as type_name, cl.content, cl.changed_on
from full_records fr join
subdomains sd
on fr.subdomain_id = sd.id join
types t
on fr.type_id = t.id join
changelog cl
on fr.id = cl.full_record_id
where fr.domain_id = 2
)
select cte.*
from (select cte.*,
row_number() over (partition by domain_id, subdomain_name, type_name, content
order by changed_on desc
) as seqnum
from cte
) cte
where seqnum = 1;
Note that I added table aliases so the query is easier to write and to read.
I'm having an issue updating a table with a select using multiple joins. I feel like everything is in place but I'm getting some syntax problems around the end, as commented below.
UPDATE ambition.ambition_totals a
INNER JOIN (SELECT
c.user AS UserID,
COUNT(*) AS dealers,
ROUND((al.NumberOfDealers / al.NumberOfDealerContacts) * 100 ,2) AS percent
FROM contact_events c
JOIN users u
ON c.user = u.id
JOIN dealers d
ON c.dealer_num = d.dealer_num
LEFT JOIN (
SELECT user_id, COUNT(*) AS NumberOfDealerContacts,
SUM(CASE WHEN ( d.next_call_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS NumberOfDealers
FROM attr_list AS al
JOIN dealers AS d ON d.csr = al.data
WHERE al.attr_id = 14
GROUP BY user_id)) as al
ON al.user_id = a.ext_id -- this is where I have a syntax error
SET a.dealers_contacted = al.dealers,
a.percent_up_to_date = al.percent;
As shown, I'm getting the data needed from these joins but I'm unable to update based on my ON clause in the final join. The select itself works apart from this, but I'm just trying to alter it to update a table.
I'm sure I'm just overlooking something in the syntax but I get an error that 'every derived table must have its own alias'.
UPDATE
Original working select that needs to be converted into the update:
SELECT
c.user AS UserID,
COUNT(*) AS Number_of_recorded_events,
ROUND((al.NumberOfDealers / al.NumberOfDealerContacts) * 100 ,2) AS Percentage_up_to_date
FROM contact_events c
JOIN users u
ON c.user = u.id
JOIN dealers d
ON c.dealer_num = d.dealer_num
LEFT JOIN (
SELECT user_id, COUNT(*) AS NumberOfDealerContacts,
SUM(CASE WHEN ( d.next_call_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS NumberOfDealers
FROM jackson_id.attr_list AS al
JOIN jfi_dealers.dealers AS d ON d.csr = al.data
WHERE al.attr_id = 14
GROUP BY user_id) AS al
ON al.user_id = c.user
GROUP BY UserID;
'every derived table must have its own alias'
This error is pretty clear. A derived table is when you put a subquery in a FROM clause or JOIN clause, which you do twice in your query.
Every time you do this, you must give each of these derived table subqueries an alias, so you can reference columns returned by the subquery.
Like:
SELECT t.foo FROM (SELECT foo FROM MyTable) AS t
This must be done for every such subquery. In your case, you have something like this form:
UPDATE a
INNER JOIN (
SELECT ... FROM c JOIN u JOIN d
LEFT JOIN (SELECT ... FROM al JOIN d ...)
) AS al
SET ...
You have one level of subquery, which you give the alias al.
But you don't give an alias for the innermost subquery, the one you did a LEFT JOIN on. That one needs an alias too.
P.S.: This question is actually a duplicate of What is the error "Every derived table must have its own alias" in MySQL? from 2009. I know Stack Overflow encourages us to close new questions as duplicates if there is already an old answer. But I also know the reality is that people tend not to search old posts much.
On the other hand, that old Stack Overflow post from 2009 is literally the first result when I google for the error string 'every derived table must have its own alias'.
This is my Query I want to get latest record in each group.I have two table t_service_request and t_request_chkpoint
t_service_request
------------
LTS,JFT,CUS_NO,REQUETST_ID...
t_request_chkpoint
------------
LTS ,REQUETST_ID...
Both table match by REQUETST_ID.
I want to group by cus_no in table t_service_request
SELECT S.*, A.ID as CID, A.ENTRY_ID, A.LTS
FROM maintenance.t_service_request S
WHERE JFT IN (
SELECT MAX(JFT)
FROM maintenance.t_service_request
GROUP BY CUS_NO
) LEFT OUTER JOIN maintenance.t_request_chkpoint A
ON S.REQUEST_ID = A.REQUEST_ID where S.COMPANY_ID = '0002' AND S.STATE >= 3 AND A.STATE >= 3
but didn't work any suggestions ?
t_service_request
------------
LTS|JFT|CUS_NO|REQUETST_ID|
t_request_chkpoint
------------
|LTS|REQUETST_ID|
Join above two table(Request_id) and select latest JFT in each CUS_NO
Try this, maybe works;)
SELECT DISTINCT
S.*,
A.ID AS CID,
A.ENTRY_ID,
A.LTS
FROM maintenance.t_service_request S
LEFT JOIN maintenance.t_request_chkpoint A ON A.REQUETST_ID = S.REQUETST_ID AND A.STATE >= 3
WHERE S.JFT = (SELECT MAX(B.JFT)
FROM maintenance.t_service_request B
WHERE B.CUS_NO = S.CUS_NO
GROUP BY B.CUS_NO)
AND S.COMPANY_ID = '0002' AND S.STATE >= 3
I think your sql may have some syntax errors and I am not sure I've misunderstood your requirement or not.
I must admit, I still don't understand what you are asking. Your query, however, is incomplete, and maybe fixing it solves your problem already.
You say you want "to get latest record in each group" and in your query you are looking for the maximum JFT per CUS_NO. Then, however you are only comparing the JFT and not the CUS_NO.
Moreover, your query is syntactically incorrect, as it has two WHERE clauses. Last but not least, (outer) join criteria (state >= 3 here) belongs in the ON clause, not in the WHERE clause.
Here is the corrected query:
select
sr.*,
rc.id as cid,
rc.entry_id,
rc.lts
from maintenance.t_service_request sr
left outer join maintenance.t_request_chkpoint rc on rc.request_id = sr.request_id
and rc.state >= 3
where sr.company_id = '0002' and sr.state >= 3
and (sr.cus_no, sr.jft) in
(
select cus_no, max(jft)
from maintenance.t_service_request
group by cus_no
);
How can I use 1 cross join and 2 left joins (sum group by) in one MySQL db query?
The following works but the count results is wrong (it returns both COUNT - same result and wrong result).
SELECT
n_users.username, n_users.email,
COUNT(n_messages.ads_id ) AS msg_cnt,
COUNT(`n_coversation`.user_id ) AS cnv_cnt,
SUM(n_transaction.debit), SUM(n_transaction.credit)
FROM
n_users JOIN (n_ads , n_messages) ON
(n_ads.user_id=n_users.id AND n_messages.ads_id=n_ads.id )
LEFT JOIN n_coversation ON (n_coversation.user_id=n_users.id)
LEFT JOIN n_transaction ON (n_transaction.user_id=n_users.id)
WHERE
n_users.id =5
GROUP BY
n_transaction.user_id
I have the following query :
(select xyz.* from
(select xt.image, p.*, pc.categoryid, c.category,
(select value from xcart_extra_field_values
where efv.productid=p.productid and efv.fieldid = 2) as Type,
(select value from xcart_extra_field_values
where efv.productid=p.productid and efv.fieldid = 1) as Zone
FROM xcart_products p
inner join xcart_products_categories pc
on p.productid=pc.productid
inner join xcart_categories c
on pc.categoryid=c.categoryid
inner join xcart_extra_field_values efv
on p.productid=efv.productid
inner join xcart_images_T xt
on p.productid=xt.id) xyz
where categoryid='1' and Type='2' and Zone='1'
group by productid)
But when I execute this query in phpmyadmin it displays a error messgae :
#1242 - Subquery returns more than 1 row
Whats wrong in the query.Please help. Thanks in advance.
I think (part of) the problem is that you are re-using an alias in a wrong location.
You should one use an alias once, and don't mix them for different instances of the same table.
(select xyz.* from
(select xt.image, p.*, pc.categoryid, c.category,
(select value from xcart_extra_field_values efv2
where efv2.productid=p.productid and efv2.fieldid = 2) as Type,
(select value from xcart_extra_field_values efv3
where efv3.productid=p.productid and efv3.fieldid = 1) as Zone
FROM xcart_products p
inner join xcart_products_categories pc
on p.productid=pc.productid
inner join xcart_categories c
on pc.categoryid=c.categoryid
inner join xcart_extra_field_values efv1
on p.productid=efv1.productid
inner join xcart_images_T xt
on p.productid=xt.id) xyz
where categoryid='1' and Type='2' and Zone='1'
group by productid)
So use a unique alias efvx for each xcart_extra_field_values table instance.
Execute each subquery manually in phpmyadmin and see which one is returning more than one row and you have your answer. Another option is to add a limit of 1 to each subquery to make sure only one row is returned. Of course it is better to look for the bug and solve it.