I have the following select query. I want to avoid getting the duplicated "EN" row when "ES" row is present. Like prefer ES over EN.
SELECT s.soft_id,s.groupby,s.packageid,s.name,s.area,l.min,GROUP_CONCAT(DISTINCT JSON_ARRAY(s.version,s.detailid,s.filesize,s.updatetime)) versions
FROM software s
INNER JOIN langs l ON s.lang_id=l.lang_id
INNER JOIN devices_type t ON (s.familylock_id=t.familylock_id OR (s.familylock_id=0 AND s.devicelock_id=t.device_type_id))
INNER JOIN devices d ON t.device_type_id=d.device_type_id
INNER JOIN users u ON d.user_id=u.user_id
WHERE s.groupby IN(1,2,3)
AND u.token="abc"
AND d.serialno="123456789"
AND l.min IN("ES","EN")
GROUP BY s.soft_id,s.groupby,s.packageid,s.name,s.area,l.min ORDER BY s.name ASC
This is the example result. And i want to get rid of AUDI and AUTOSEARCH "EN" rows.
Image
You need to change your WHERE condition to exclude a row with l.min = 'EN' if a row with l.min = 'ES' exists. You can do this using a NOT EXISTS clause; changing the
AND l.min IN("ES","EN")
condition to
AND (l.min = 'ES' OR
l.min = 'EN' AND NOT EXISTS (SELECT *
FROM software s2
JOIN langs l2 ON l2.lang_id = s2.lang_id
WHERE s2.soft_id = s.soft_id
AND l2.min = 'ES')
)
Small sample demo on SQLFiddle
Is the below helps? I could not validate the script as I don't have sample data but below idea should help you to set the priority.
DB Fiddle
WITH preference AS
(
SELECT s.*, row_number() OVER (PARTITION BY s.soft_id
ORDER BY s.packageid,
CASE
WHEN l.min = 'ES'
THEN 'A'
ELSE 'B'
END) priority
FROM software s
INNER JOIN langs l ON s.lang_id=l.lang_id
WHERE l.min IN("ES","EN")
)
SELECT *
FROM preference
WHERE priority = 1;
Related
I have a query which gives result as below, how to replace duplicate values with NULL
Query:
SELECT
word.lemma,
synset.definition,
synset.pos,
sampletable.sample
FROM
word
LEFT JOIN
sense ON word.wordid = sense.wordid
LEFT JOIN
synset ON sense.synsetid = synset.synsetid
LEFT JOIN
sampletable ON synset.synsetid = sampletable.synsetid
WHERE
word.lemma = 'good'
Result:
Required Result: all the greyed out results as NULL
First, this is the type of transformation that is generally better done at the application level. The reason is that it presupposes that the result set is in a particular order -- and you seem to be assuming this even with no order by clause.
Second, it is often simpler in the application.
However, in MySQL 8+, it is not that hard. You can do:
SELECT w.lemma,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY w.lemma, ss.definition ORDER BY st.sample) = 1
THEN ss.definition
END) as definition,
ss.pos,
st.sample
FROM word w LEFT JOIN
sense s
ON w.wordid = s.wordid LEFT JOIN
synset ss
ON s.synsetid = ss.synsetid LEFT JOIN
sampletable st
ON ss.synsetid = st.synsetid
WHERE w.lemma = 'good'
ORDER BY w.lemma, ss.definition, st.sample;
For this to work reliably, the outer ORDER BY clause needs to be compatible with the ORDER BY for the window function.
If you are using Mysql 8 try with Rank().. As I didn't have your table or data couldn't test this query.
SELECT
word.lemma
,case when r = 1 synset.definition else null end as definition
,synset.pos
,sampletable.sample
FROM
(
SELECT
word.lemma
,synset.definition
,synset.pos
,sampletable.sample
,RANK() OVER (PARTITION BY synset.definition ORDER BY synset.definition) r
FROM
(
SELECT
word.lemma,
synset.definition,
synset.pos,
sampletable.sample
FROM
word
LEFT JOIN
sense ON word.wordid = sense.wordid
LEFT JOIN
synset ON sense.synsetid = synset.synsetid
LEFT JOIN
sampletable ON synset.synsetid = sampletable.synsetid
WHERE
word.lemma = 'good'
) t
)t1;
I want get some of data with one distinct email.
My code is below:
SELECT DISTINCT Email,
Degree,
Majority
FROM job_education a
WHERE a.Status = 'Active'
AND a.IdEducationLevel = (
SELECT Max(b.IdEducationLevel)
FROM job_education b
WHERE b.Status='Active'
AND a.Email = b.Email
)
Thanks your kindness before
Your code should be fine, although I would fix the table aliases:
SELECT je.*
FROM job_education je
WHERE je.Status = 'Active' AND
je.IdEducationLevel = (SELECT MAX(je2.IdEducationLevel)
FROM job_education je2
WHERE je2.Status = 'Active' AND je2.Email = je.Email
);
If you are getting multiple rows for a given email -- and you want only one row -- then use a better id in the subquery:
SELECT je.*
FROM job_education je
WHERE je.Status = 'Active' AND
je.job_education_id = (SELECT je2.job_education_id
FROM job_education je2
WHERE je2.Status = 'Active' AND je2.Email = je.Email
ORDER BY IdEducationLevel DESC, job_education_id DESC
LIMIT 1
);
I have invented an id called job_education_id for this purpose. Note that this query uses ORDER BY and LIMIT rather than an aggregation function.
you should use a join
(the subselect can't see the upper reference to the table a)
SELECT DISTINCT Email,
Degree,
Majority
FROM job_education a
INNER JOIN (
SELECT b.Email, Max(b.IdEducationLevel) max_IdEducationLevel
FROM job_education b
WHERE b.Status='Active'
GROUP BY b.Email
) t ON a.Email = t.Email and a.IdEducationLevel = t.maxy_IdEducationLevel
WHERE a.Status = 'Active'
Ho can i only fetch the rows with the highest cvID value?
current code
SELECT
CollectionVersionBlocks.cID,
CollectionVersionBlocks.cbDisplayOrder,
CollectionVersionBlocks.cvID,
btContentLocal.bID,
btContentLocal.content
FROM
CollectionVersionBlocks
INNER JOIN btContentLocal
ON CollectionVersionBlocks.bID = btContentLocal.bID
WHERE (CollectionVersionBlocks.cID = 259)
AND CollectionVersionBlocks.isOriginal = 1
AND CollectionVersionBlocks.arHandle = 'main'
AND btContentLocal.content != ''
I want to get the row at the bottom (where the cvID value is 10).
This is a test statement for a bigger result set -
I will eventually need a set of results from perset cIDs (CollectionVersionBlocks.cID = 259 OR CollectionVersionBlocks.cID = 260... upto 800)
updated screenshots
1) too few results
2) un grouped results
To get the highest row per group (from your question i assume cID as a single group) you can do so by using a self join on the maxima of your desired column by using additional condition in in your third join i.e ON(c.cID=cc.cID AND c.cvID=cc.cvID)
SELECT
c.cID,
c.cbDisplayOrder,
c.cvID,
b.bID,
b.content
FROM
CollectionVersionBlocks c
INNER JOIN btContentLocal b
ON (c.bID = b.bID)
INNER JOIN
(SELECT cID, MAX(cvID) cvID FROM CollectionVersionBlocks GROUP BY cID) cc
ON(c.cID=cc.cID AND c.cvID=cc.cvID)
WHERE (c.cID = 259)
AND c.isOriginal = 1
AND c.arHandle = 'main'
AND b.content != ''
and for multiple groups you can just use WHERE c.cID IN(259,....800)
Try below Query:
SELECT CollectionVersionBlocks.cID,CollectionVersionBlocks.cbDisplayOrder, CollectionVersionBlocks.cvID , btContentLocal.bID , btContentLocal.content
FROM CollectionVersionBlocks
INNER JOIN btContentLocal
ON CollectionVersionBlocks.bID=btContentLocal.bID
WHERE (CollectionVersionBlocks.cID = 259)
AND CollectionVersionBlocks.isOriginal=1 AND CollectionVersionBlocks.arHandle ='main' AND btContentLocal.content !='' and CollectionVersionBlocks.cID in
(
SELECT Max(CollectionVersionBlocks.cID)
FROM CollectionVersionBlocks
INNER JOIN btContentLocal
ON CollectionVersionBlocks.bID=btContentLocal.bID
WHERE (CollectionVersionBlocks.cID = 259)
AND CollectionVersionBlocks.isOriginal=1 AND CollectionVersionBlocks.arHandle ='main' AND btContentLocal.content !='' )
The query below sums up points from the MySQL table "comment" when the following conditions are met:
The loginid when l.username = '$profile' is found.
All the submissionids are found that have the loginid from #1 above.
All the commentids with the submissionids from #2 above are found, and the corresponding points are summed.
Now, how could I make a different query that returns an array of all of the comments in #3 above rather than summing the points?
Here are the MySQL tables involved:
login:
logind username created activated
submission:
submissionid loginid
comment:
commentid submissionid points comment
Query:
SELECT
l.loginid,
l.username,
l.created,
l.activated,
COALESCE(scs.total, 0) AS commentsreceivedvalue
FROM login l
LEFT JOIN (
SELECT S2.loginid, SUM(C2.points) AS total
FROM submission S2
INNER JOIN comment C2
ON S2.submissionid = C2.submissionid
GROUP BY S2.loginid
) scs ON scs.loginid = l.loginid
WHERE l.activated = 1
AND l.username = '$profile'
GROUP BY l.loginid
ORDER BY commentsreceivedvalue DESC
Isn't it as simple as:
SELECT l.loginid, l.username, l.created, l.activated, scs.commentid, scs.comment
FROM login AS l
LEFT JOIN (SELECT S2.loginid, c2.commentid, c2.comment
FROM submission AS S2
JOIN comment AS C2 ON S2.submissionid = C2.submissionid
) AS scs ON scs.loginid = l.loginid
WHERE l.activated = 1
AND l.username = '$profile'
ORDER BY scs.commentid DESC;
The outer GROUP BY in the original was not doing anything useful. The ORDER BY in the original was replaced here by the ordering in reverse order of comment ID, which is an approximation to reverse chronological order (most recent first, in other words).
How do I put these two queries into a single query?
select count(id) as cnt from {$site_id}.proofingv2_packages where active='1'
select count(id) as cnt from {$site_id}.proofingv2_package_options where active='1' and parent={$row["id"]} order by sort
$row['id'] is the id field from the first query. I am trying to determine if there are any valid packages. A valid package must be active and have at least 1 active option. Running 2 queries for this doesn't seem right.
Can anyone help?
select count(id) as cnt from
{$site_id}.proofingv2_packages pp
INNER JOIN
{$site_id}.proofingv2_package_options
pt ON pp.active = pt.Active AND
pp.Active = 1
if the id is the PK or FK on the same on both tables use this query
select count(id) as cnt from
{$site_id}.proofingv2_packages pp
INNER JOIN {$site_id}.proofingv2_package_options pt ON pp.id= pt.id
AND pp.Active = 1
SELECT IF(count(*) > 0, 1, 0) AS isValid
FROM {$site_id}.proofingv2_packages pp
INNER JOIN {$site_id}.proofingv2_package_options ppo ON ppo.parent = pp.id
WHERE pp.active = '1'
AND ppo.active = '1'
This should return 1 if there are valid packages or 0 if not