ExpressionEngine query module and ordering SQL UNION - mysql

I'm receiving a MySQL Error on this code in ExpressionEngine 1.6.4 (very old version)
{exp:query limit="10" paginate="bottom"
sql="SELECT 'gallery' AS `content_type`, `cat_id` AS `entry_id`, `recent_entry_date` AS `entry_date`
FROM `exp_gallery_categories`
WHERE `gallery_id` = 9 AND total_files > 0
UNION
SELECT 'video' AS `content_type`, `entry_id`, `entry_date`
FROM `exp_weblog_titles`
WHERE `weblog_id` = 6 ORDER BY `entry_date` DESC"
}
<p>{content_type} - {entry_id} - {entry_date format="%d %F %Y"}</p>
{paginate}{pagination_links}{/paginate}
{/exp:query}
MySQL returns this:
MySQL ERROR: Error Number: 1054
Description: Unknown column 'entry_date' in 'order clause'
Query: SELECT COUNT(*) AS count FROM `exp_gallery_categories` WHERE `gallery_id` = 9 AND total_files > 0 UNION SELECT COUNT(*) AS count FROM `exp_weblog_titles` WHERE `weblog_id` = 6 ORDER BY `entry_date` DESC
It seems like EE is modifying my query before MySQL and making it fail (On a SQL client this works smoothly).

The answer is to patch mod.query.php to stop modifing the query
$query = $DB->query("SELECT COUNT(*) AS count FROM ({$sql}) AS query");
Here is the ultimate in-depth answer by Dom Stubbs: ExpressionEngine 1 Query Module and Ordering SQL UNION

I am assuming your select queries work. Try below:
sql="SELECT * FROM
(SELECT gallery AS content_type, cat_id AS entry_id,
recent_entry_date AS entry_date
FROM exp_gallery_categories
WHERE gallery_id = 9 AND total_files > 0
UNION
SELECT video AS content_type, entry_id, entry_date
FROM exp_weblog_titles
WHERE weblog_id= 6
) AS TEMP
ORDER BY entry_date DESC"
EDIT: Count query:
SELECT COUNT(*) AS count
FROM
( SELECT COUNT(*) AS count,
recent_entry_date AS entry_date
FROM exp_gallery_categories
WHERE gallery_id = 9 AND total_files > 0
UNION
SELECT COUNT(*) AS count,
entry_date
FROM exp_weblog_titles
WHERE weblog_id = 6
) AS TEMP
ORDER BY entry_date DESC

Related

How to check if id occurs in other table in MySQL

I have a table an_visit that has column visit_id. There is also a table an_transaction that has some visit_id too.
I would like to get a new column in MySQL based on if visit_id occurs in both tables. My approach:
SELECT visit_id, datetime_add, ISNULL((SELECT
1
FROM an_transaction
WHERE an_transaction.visit_id = an_visit.visit_id), 0)
FROM an_visit
WHERE datetime_add >= '2021-08-01'
LIMIT 50
But I got this error: MySQLdb.OperationalError: (1582, "Incorrect parameter count in the call to native function 'ISNULL'"). What do I do wrong, please?
SELECT visit_id, datetime_add, ISNULL((SELECT
1
FROM an_transaction
WHERE an_transaction.visit_id = an_visit.visit_id limit 1))
FROM an_visit
WHERE datetime_add >= '2021-08-01'
LIMIT 50
OR
SELECT visit_id, datetime_add, IFNULL((SELECT
1
FROM an_transaction
WHERE an_transaction.visit_id = an_visit.visit_id limit 1),0)
FROM an_visit
WHERE datetime_add >= '2021-08-01'
LIMIT 50

SQL numbering merge if string is the same

I want to create a stats page for my website. However I have the problem that if I run my query it will not be merged if the sting is the same. Any idea how to fix this?
My query:
SELECT * FROM (
SELECT dj_1, count(*) AS uren
FROM dj_rooster
WHERE week = '28' GROUP BY id_1
ORDER BY count(*) DESC
) x
UNION ALL
SELECT * FROM (
SELECT dj_1, count(*) AS uren
FROM djpaneel_shows_uren
WHERE week = '28' AND active = '1'
GROUP BY dj_1
ORDER BY count(*) DESC
) x
My results:
Jack - 7
Jeremy - 5
Jack - 1
Thanks in advance for your help
There is no need to aggregate twice or more.
Use UNION ALL to get all the rows from the 2 tables and then aggregate:
SELECT t.dj_1, COUNT(*) AS uren
FROM (
SELECT dj_1 FROM dj_rooster
WHERE week = '28'
UNION ALL
SELECT dj_1 FROM djpaneel_shows_uren
WHERE week = '28' AND active = '1'
) t
GROUP BY t.dj_1
ORDER BY uren DESC

Reorder results from another query

SELECT * FROM (
SELECT * FROM cars WHERE site = '5'
ORDER BY cost DESC LIMIT 0 , 10
)
ORDER BY time
How would I execute a sql query like this? So first it selects the 10 cars with the highest cost, THEN it reorders those 10 cars by what time they were added to the DB.
I tried to figure it out but I just cannot get a grip on the syntax :P
Just give an alias to the sub-query.
SELECT * FROM (
SELECT * FROM `cars` WHERE `site` = '5'
ORDER BY `cost` DESC LIMIT 0 , 10
)t
ORDER BY `time`;
This query will give you the desired results
SELECT * FROM ( SELECT * FROM cars WHERE site = 5
ORDER BY cost DESC LIMIT 0 , 10 ) as t ORDER BY time

1242 Subquery returns more than 1 row

I got this error, I hope you may help me. I want to show a certain item in a search.
SELECT p.id, p.property_rank, p.pic_numb, p.att_numb, p.confirm, p.finalized ,p.deleted, p.user_id, p.add_date, p.visit_time,p.visit_date,p.sent_numb, p.contact_numb, zip_name, zip_id, p.street, p.sp_featured, p.property_title, p.b_price_unit, p.b_price_si, p.b_price, p.b_price, p.street_no, p.field_54,
p.field_409,
( SELECT `listing_type`.`id`
FROM `res_rpl_listing_types` AS `listing_type`
WHERE `listing_type`.`id` = (
SELECT `listing`.`type`
FROM `res_rpl_listings` AS `listing`
WHERE `listing`.`id` = p.`listing`)
) AS `listing_type_id`,
p.listing, p.googlemap_ln, p.googlemap_lt, p.category, p.b_bedrooms, p.b_bathrooms, p.sp_openhouse, p.b_price_period, p.b_lot_area_unit, p.b_lot_area_si, p.b_lot_area, p.b_lot_area, p.b_living_area_unit, p.b_living_area_si, p.b_living_area, p.b_living_area, p.description, p.sp_hot, p.sp_forclosure
FROM res_rpl_properties AS p
WHERE 1 AND p.`type` = '0' AND p.`confirm` = '1' AND p.`finalized` = '1' AND p.`deleted` = '0' AND p.`category` IN(9,8,10)
ORDER BY p.add_date DESC
LIMIT 0 , 12
The error is telling you that your subquery (selected as listing_type_id) returns more than one row. To rephrase - it's returning more than one value for listing_type_id. You should limit the results from the subquery to just one.
You have two options:
OR select just the first row of subquery
(SELECT `listing_type`.`id`
FROM `res_rpl_listing_types` AS `listing_type`
WHERE `listing_type`.`id` = (
SELECT `listing`.`type`
FROM `res_rpl_listings` AS `listing`
WHERE `listing`.`id` = p.`listing`
LIMIT 1
)
LIMIT 1
) AS `listing_type_id`
OR use IN to allow multiple comparation
(SELECT `listing_type`.`id`
FROM `res_rpl_listing_types` AS `listing_type`
WHERE `listing_type`.`id` IN (
SELECT `listing`.`type`
FROM `res_rpl_listings` AS `listing`
WHERE `listing`.`id` = p.`listing`)
LIMIT 1
) AS `listing_type_id`
The problem is there is 2 subqueries and you need to treat both. Both of them need to be limited to 1 row only.

SELECT COUNT all rows and return just 10 + and a counted total

What I am trying to get is to send a request to DB that will:
1 count all rows
2 return 10 rows
SELECT count( * ) AS 'total'
FROM stuff
WHERE usr = '65'
LIMIT 10
So it is supposed to return 10 results PLUS 'total' with the number of all rows.
So far it returns the counted amount of rows only....
-- count records first
SET #total = (
SELECT count( * ) AS 'total'
FROM `stuff`
WHERE `usr` = '65'
);
-- then, select your ten records and include the total from previous operation
SELECT *, #total
FROM `stuff`
WHERE `usr` = '65'
LIMIT 10
You'll need to split the 2 concerns out, and then recombine them:
SELECT s.col1, s.col2, s.col3, x.total
FROM `stuff` s
CROSS JOIN
(
SELECT count(*) AS total
FROM `stuff`
WHERE `usr` = '65'
) x
WHERE s.`usr` = '65'
LIMIT 10;
Fiddle here
RDBMs like SqlServer and Oracle allow for CTE's which would allow you to DRY up the repeated select ... where. Some options in MySql here
If you want all rows to be counted and limit the result to 10 then you can do it the following way
SELECT SQL_CALC_FOUND_ROWS * FROM `stuff` WHERE `usr` = '65' LIMIT 10
SELECT FOUND_ROWS();