Sorting SQL results in the query - mysql

I have a query like this:
SELECT A.*,
B.surname,
B.name,
C.url_address,
(SELECT Concat(file_path, '/', file_name) AS image
FROM psuploadedfiles B
WHERE enum = 3
AND category = A.id_user
ORDER BY number ASC
LIMIT 1) AS image2,
(SELECT Concat(file_path, '/', file_name) AS image
FROM psuploadedfiles B
WHERE enum = 3
AND category = A.post_id
ORDER BY number ASC
LIMIT 1) AS image
FROM psposts A
LEFT JOIN psuserdetails B
ON B.id_user = A.id_user
LEFT JOIN psuser C
ON C.id_user = A.id_user
WHERE A.enable = '1'
AND ( A.id_user = 21
OR ( A.id_user = '7'
OR A.id_user = '1'
OR A.id_user = '5' ) )
ORDER BY date DESC
LIMIT 0, 25;
In the psPosts table, I have a subscriptions_date column (containing a date in yyyy-mm-dd format) where subscriptions_date is date until when the post will be promoted.
How can I sort the results in such a way that there are posts at the top containing subscriptions_date current or future date (i.e. promoted), and underneath the other posts?

Something like...
ORDER BY
CASE WHEN A.subscriptions_date >= NOW() THEN 0 ELSE 1 END,
date
The first sort criteria splits data into two groups, with current or future subscriptions in first place. Within each group, data is then sorted by date.

Related

INNER JOIN DIM TABLE TO FOUND ID OF FIPS

I am currently trying to query the fips code and sum of the amount of cases for that code from the cases table and the id of the fips code for the subquery from the dim_counties table.
Here's what I have so far that has worked:
SELECT DISTINCT C.FIPS,
SUM(C.CASES) AS SUMS
FROM DIM_DATE_MONTH B, CASES C
where 1=1
and B.DATE_SHORT = SUBSTR(TO_CHAR(C.DAY_OF, 'MONTH'), 1,3)
AND B.DATE_YR = SUBSTR(EXTRACT(YEAR FROM C.DAY_OF),1,4)
AND SUBSTR(TO_CHAR(C.DAY_OF, 'MONTH'), 1,3) = 'JAN'
AND SUBSTR(EXTRACT(YEAR FROM C.DAY_OF),1,4) = '2020'
GROUP BY C.FIPS
ORDER BY SUMS DESC
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY;
What I have attempted that doesn't work
SELECT A.COUNTY_NBR,
A.FIPS,
D.SUMS
FROM DIM_COUNTIES A
INNER JOIN(
SELECT DISTINCT C.FIPS,
SUM(C.CASES) AS SUMS
FROM DIM_DATE_MONTH B, CASES C
where 1=1
and B.DATE_SHORT = SUBSTR(TO_CHAR(C.DAY_OF, 'MONTH'), 1,3)
AND B.DATE_YR = SUBSTR(EXTRACT(YEAR FROM C.DAY_OF),1,4)
AND SUBSTR(TO_CHAR(C.DAY_OF, 'MONTH'), 1,3) = 'JAN'
AND SUBSTR(EXTRACT(YEAR FROM C.DAY_OF),1,4) = '2020'
GROUP BY C.FIPS
ORDER BY SUMS DESC
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY)D ON D.SUM) D ON C.FIPS = A.FIPS;

Get only 1 result per group of ID

I have a list of records (domestic_helper_idcards) and I want to return only one card per staff (domestic_helper_id) that is not deleted (is_deleted = 0), and that has the card_expiration_date furthest in the future (latest expiry date).
Have tried grouping and so on, but cant get it to work. Code below:
SELECT * FROM domestic_helper_idcard
where
is_deleted = 0
order by card_expiration_date desc
This returns the following (image):
I want only records with ID 4 and 5 to be returned. Anyone?
You could use a join with the subquery grouped by domestic_helper_id with an aggregated function eg: max()
SELECT d.*
FROM domestic_helper_idcard d
inner join (
select domestic_helper_id, max(id) max_id
from domestic_helper_idcard
where is_deleted = 0
group by domestic_helper_id
) t on t.domestic_helper_id = d.domestic_helper_id and t.max_id = d.id
order by d.card_expiration_date desc
and as suggested by Jens after clarification using max card_expiration_date
SELECT d.*
FROM domestic_helper_idcard d
inner join (
select domestic_helper_id, max(card_expiration_date) max_date
from domestic_helper_idcard
where is_deleted = 0
group by domestic_helper_id
) t on t.domestic_helper_id = d.domestic_helper_id and t.max_date = d.max_date
order by d.card_expiration_date desc

Join between sub-queries in SQLAlchemy

In relation to the answer I accepted for this post, SQL Group By and Limit issue, I need to figure out how to create that query using SQLAlchemy. For reference, the query I need to run is:
SELECT t.id, t.creation_time, c.id, c.creation_time
FROM (SELECT id, creation_time
FROM thread
ORDER BY creation_time DESC
LIMIT 5
) t
LEFT OUTER JOIN comment c ON c.thread_id = t.id
WHERE 3 >= (SELECT COUNT(1)
FROM comment c2
WHERE c.thread_id = c2.thread_id
AND c.creation_time <= c2.creation_time
)
I have the first half of the query, but I am struggling with the syntax for the WHERE clause and how to combine it with the JOIN. Any one have any suggestions?
Thanks!
EDIT: First attempt seems to mess up around the .filter() call:
c = aliased(Comment)
c2 = aliased(Comment)
subq = db.session.query(Thread.id).filter_by(topic_id=122098).order_by(Thread.creation_time.desc()).limit(2).offset(2).subquery('t')
subq2 = db.session.query(func.count(1).label("count")).filter(c.id==c2.id).subquery('z')
q = db.session.query(subq.c.id, c.id).outerjoin(c, c.thread_id==subq.c.id).filter(3 >= subq2.c.count)
this generates the following SQL:
SELECT t.id AS t_id, comment_1.id AS comment_1_id
FROM (SELECT count(1) AS count
FROM comment AS comment_1, comment AS comment_2
WHERE comment_1.id = comment_2.id) AS z, (SELECT thread.id AS id
FROM thread
WHERE thread.topic_id = :topic_id ORDER BY thread.creation_time DESC
LIMIT 2 OFFSET 2) AS t LEFT OUTER JOIN comment AS comment_1 ON comment_1.thread_id = t.id
WHERE z.count <= 3
Notice the sub-query ordering is incorrect, and subq2 somehow is selecting from comment twice. Manually fixing that gives the right results, I am just unsure of how to get SQLAlchemy to get it right.
Try this:
c = db.aliased(Comment, name='c')
c2 = db.aliased(Comment, name='c2')
sq = (db.session
.query(Thread.id, Thread.creation_time)
.order_by(Thread.creation_time.desc())
.limit(5)
).subquery(name='t')
sq2 = (
db.session.query(db.func.count(1))
.select_from(c2)
.filter(c.thread_id == c2.thread_id)
.filter(c.creation_time <= c2.creation_time)
.correlate(c)
.as_scalar()
)
q = (db.session
.query(
sq.c.id, sq.c.creation_time,
c.id, c.creation_time,
)
.outerjoin(c, c.thread_id == sq.c.id)
.filter(3 >= sq2)
)

MySQL query sub query or grouping

Each modx_site_content record may have several records in modx_site_tmplvar_contentvalues.
I need to retrieve both modx_site_tmplvar_contentvalues.value where the tvv.tmplvarid = 3 AND the tvv.tmplvarid = 1. where tvv.tmplvarid is a future date, I need to return the tvv.value of tvv.tmplvarid 3 which is a comma separated list of tags.
This query does not return the values I need & I'm not sure how to get just what I want.
SELECT sc.id, sc.pagetitle, tvv.value, tvv.tmplvarid, tvv.id, tvv.value
FROM modx_site_content sc
left join modx_site_tmplvar_contentvalues tvv on tvv.contentid = sc.id
where published = '1'
and (tvv.tmplvarid = '3' and tvv.value >= curdate())
order by sc.id;
basically in the end I need to return only the list of tags (tvv.tmplvarid = 3) where the other associated record (tvv.tmplvarid = 1) is a date in the future.
Any thoughts, can this be done with grouping instead? I don't actually need anything from the modx_site_content table.
So you need to return the tags both rows in the modx_site_tmplvar_contentvalues table that has tmplvarid of 1 and 3 both related to the same modx_site_content, but only when the tmplvarid 3 row has a datetime field in the future?
I would do two separate joins to the modx_site_tmplvar_contentvalues tabe:
SELECT tOne.value, tThree.value
FROM modx_site_tmplvar_contentvalues tOne
INNER JOIN modx_site_content c ON tOne.contentid = c.id
INNER JOIN modx_site_tmplvar_contentvalues tThree ON tThree.contentid = c.id
WHERE c.published = 1
AND tOne.tmplvarid = 1
AND tThree.tmplvarid = 3 AND tThree.date > NOW()
SQL Fiddle: http://sqlfiddle.com/#!2/a4031/2
I figured it out. Amazing what you can do if you just read the docs ;)
select tv.contentid, tv.value as eventdate, sc.id, sc.pagetitle, tvv.value from
(
select * from modx_site_tmplvar_contentvalues cv
where cv.tmplvarid = 3
and cv.value >= curdate()
) as tv
left join modx_site_content sc on sc.id = tv.contentid
left join modx_site_tmplvar_contentvalues tvv on tvv.contentid = sc.id
where (tvv.tmplvarid = 1)
order by value asc

MySQL Query, how to select data based on a condition in a different record in the same table?

Having some trouble getting my here around this query & wondering if anyone can help:
I'm trying to select all the tvv.value[s] from the modx_site_tmplvar_contentvalues where the tvv.tmplvarid = 1 and the tvv.value of tvv.tmplvarid = 3 is a date greater then or equal to today.
So basically each modx_site_content.id that is published an has a parent of '24' will have at least 2 entries in the modx_site_tmplvar_contentvalues table one with an tmplvarid of '1' whose value will be a comma separated list and another with a tmplvarid of '3' which will be a datestamp.
I need to select all the values from the modx_site_tmplvar_contentvalues table where the tmplvarid is '1' [the comma separated list], where the second entry tmplvarid equaling '3' is a date greater than equal to today and the modx_site_content conditions are published = '1' and parent = '24'
Here is my query [that does not work]
SELECT sc.id, sc.pagetitle, tvv.value, tvv.tmplvarid, tvv.id
FROM modx_site_content sc
left join modx_site_tmplvar_contentvalues tvv on tvv.contentid = sc.id
where published = '1'
and parent = '24'
and (tvv.tmplvarid = '3' or tvv.tmplvarid = '1')
and tvv.value >= curdate()
group by sc.id
order by sc.id
Any help?
If my understanding is correct, you want to get data based on 2 conditions:
- tmplvarid = '1'
- tmplvarid = '3' and value >= curdate()
If so, try this:
SELECT sc.id, sc.pagetitle, tvv.value, tvv.tmplvarid, tvv.id
FROM modx_site_content sc
left join modx_site_tmplvar_contentvalues tvv on tvv.contentid = sc.id
where published = '1'
and parent = '24'
and ((tvv.tmplvarid = '3' and tvv.value >= curdate()) or (tvv.tmplvarid = '1'))
order by sc.id
Correct me if I misunderstand your question.