MySQL LIMT is a subquery? - mysql

I want to use a select statement to control the limit of another select query, I cant get it to work, what I have below. The Select in the braces returns an INT.
Im newer to MySQL so im not sure what I should use instead to get this to work.
SELECT *
FROM `tbl_prod`
WHERE prod_id = 32
ORDER BY prod_level ASC , prod_date
LIMIT
(SELECT max_count
FROM Prod_subscription
WHERE prod_id = 32)

You can't write subquery in LIMIT, but you can use dynamic SQL to make your expected result.
SET #num = (
SELECT max_count
FROM Prod_subscription
WHERE prod_id = 32);
PREPARE STMT FROM 'SELECT *
FROM `tbl_prod`
WHERE prod_id = 32
ORDER BY prod_level ASC , prod_date
LIMIT ?';
EXECUTE STMT USING #num;

Related

SQL Counting Distinct Values From Table With multiple Where possibilities [duplicate]

This question already has answers here:
How can I return pivot table output in MySQL?
(10 answers)
MySQL pivot table query with dynamic columns
(3 answers)
Closed 3 years ago.
The question is simple. How do i combine the following 2 sql queries into one.
I am using MYSQL v8.0.16 on the MYSQL Workbase UI.
SELECT Node_Type, COUNT(*) AS `count`
FROM node_table_vis
WHERE Node_SpinePlanID = "1"
GROUP BY Node_Type;
RETURNS
TYPE - COUNT
-----------
AGN 18
TJ 26
DSLAM 15
PON 18
CCJ 17
and
SELECT DISTINCT Node_SpinePlanID
FROM node_table_vis
WHERE Node_Exchange = "Exchange 1";
Thats returns
SpinePlanID
------------
1
5
10
So essentially what i want is query that looks like this?
SELECT Node_Type, COUNT(*) AS `count`
FROM node_table_vis
WHERE Node_SpinePlanID =
(
SELECT DISTINCT Node_SpinePlanID
FROM node_table_vis
WHERE Node_Exchange = "Exchange 1";
)
GROUP BY Node_Type;
So I get table that looks like
TYPE - 1 - 5 - 10
-----------------------
AGN 18 x y
TJ 26 x y
DSLAM 15 x y
PON 18 x y
CCJ 17 x y
So this is just throwing errors and not producing the goods. I was able to find the answer the top query, i was able to make the bottom, however i am unable to find an answer to combine both.
Any advice would be really appreciated.
UPDATE/EDIT
I have the following ...
SET ##group_concat_max_len = 10000;
SET #sql = null;
SELECT group_concat(distinct
concat(
'SUM(Node_SpinePlanID = ''',
Node_SpinePlanID,
''',) AS ',
Node_SpinePlanID
)
) INTO #sql
FROM node_table_vis;
SET #sql = CONCAT('SELECT Node_Type, ', #sql, ' FROM node_table_vis GROUP BY Node_Type');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
However the PREPARE stmt is not working? Getting error Code 1064 You have an SQL Error Syntax?
Any Advice on this one?
Are you looking for conditional aggregation?
SELECT Node_Type,
SUM(Node_SpinePlanID = 1) AS count_1,
SUM(Node_SpinePlanID = 5) AS count_5,
SUM(Node_SpinePlanID = 10) AS count_10
FROM node_table_vis
GROUP BY Node_Type;
You can also put the values into rows:
SELECT Node_Type, Node_SpinePlanID, COUNT(*) as cnt
FROM node_table_vis
GROUP BY Node_Type, Node_SpinePlanID;
Without dynamic SQL, probably the best you can do is to put the values in a single row is to put them in a string with two levels of aggregation:
SELECT Node_Type, GROUP_CONCAT(Node_SpinePlanID, ':', cnt SEPARATOR ',')
FROM (SELECT Node_Type, Node_SpinePlanID, COUNT(*) as cnt
FROM node_table_vis
GROUP BY Node_Type, Node_SpinePlanID
) ts
GROUP BY Node_Type;

Replacing LIMIT static value with column value

I have a table that looks like this:
ID Damage
1 10
2 7
3 153587
4 1
...1M more rows
I have another table that has a column that represents the percentile in the amount of rows I need to grab, so if its top 10 percentile the column value will be 100000 I want to grab based on damage.
Is there a way instead of saying LIMIT 100000, since the percentile changes to replace 100000 with essentially a variable or the column value?
Second table:
Days Percentile_Affected Damage_Sum
14 87000
30 161000
90 371000
...
If the ids had no gaps, you could just use the id. Instead, you can add a counting variable and use that:
select t.*
from (select t.*, (#rn := #rn + 1) as rn
from (select t.*
from t
order by id
) t cross join
(select #rn := 0) params
) t
where rn < (select "a column" from "another table");
The alternative is to construct the query and use dynamic SQL:
select #sql := replace('select t.* from t limit [limit]', [limit], "a column")
from "another table";
prepare stmt from #sql;
execute stmt;
Or, use a placeholder for the limit:
set #sql = 'select t.* from t limit ?';
select #limit := "a column"
from "another table";
prepare stmt from #sql;
execute stmt using #limit;

SQL limit result to top 50%

I tried two methods but failed in mysql.
/*see top 50% students, but this sql can't work*/
select * from student_table order by chinese_score desc limit count(*) * 0.5 ;
/*also can't work*/
set #num= floor((select count(*) from test.student_score)*0.5);
select * from student_table order by chinese_score desc limit #num ;
How to solve in mysql?
In Mysql this can be done in a single query using user defined variables.
You can store a value in a user-defined variable in one statement and
refer to it later in another statement. This enables you to pass
values from one statement to another.
SELECT * FROM (
SELECT student_table.*, #counter := #counter +1 AS counter
FROM (SELECT #counter:=0) AS initvar, student_table
ORDER BY student_table.chinese_score DESC
) AS result
WHERE counter < (#counter/2) ORDER BY chinese_score DESC;

Storing the results of a prepared statement as a table in mysql?

Is it possible to store the result of a prepared table in mysql ?
My use case is -:
I am creating two variables based on certain conditions of the source table, then fetching the randomized rows, based on this criteria. Since I have 10 of such tables, should I be 1st joining them and then doing this randomization on the "overall" passing/filtering criteria (See also #total below, which is my main criteria, PER table)
set #total=(select count(*) from tab_1 where predict_var ="4" or predict_var ="2" ) ;
set #sample= ( select #total*(70/30)) ;
PREPARE STMT FROM " SELECT * FROM tab_1 WHERE predict_var = '4' or predict_var = '2' union
(SELECT * FROM tab_1 WHERE predict_var = '0' or predict_var = '1' ORDER BY RAND() limit ? )" ;
EXECUTE STMT USING #sample;
After I have Executed this statement - I want to be storing these rows, for retrieval later, preferably in form of a table. I would like to do something like this
# incorrect syntax, but I would like something similar
create table tab_derived_1
select * from
EXECUTE STMT USING #sample;
Tip : +1 for additionally mentioning, why this does not work with prepared Statements.
Put the create table in the statement:
PREPARE STMT FROM "CREATE TABLE tab_derived_1 SELECT * FROM tab_1 WHERE predict_var = '4' or predict_var = '2' union
(SELECT * FROM tab_1 WHERE predict_var = '0' or predict_var = '1' ORDER BY RAND() limit ? )" ;
EXECUTE STMT USING #sample;
And if you want to return the results, not just store them in a table, just do a final
SELECT * FROM tab_derived_1

Mysql Syntax Error when running as prepared statment

I've this stored procedure in which I am using a prepared statment to perform two queries.Here's the procedure.
SET #uid = puserid;
SET #rangee = plimit * 50;
SET #post = 'post';
PREPARE STMT FROM
'
SELECT notifications.postid,victims.victimid,friends.friendsname,notificationrecievers.status
FROM friends,victims,notifications,notificationrecievers
WHERE victims.postid=notifications.postid
AND notificationrecievers.notificationid=notifications.notid
AND notificationrecievers.recieverid=?
AND notifications.type=?
AND friends.friendsid=victims.victimid
AND notificationrecievers.notificationid <=
(
SELECT MAX(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)a
)
AND notificationrecievers.notificationid >=
(
SELECT MIN(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)b
)
ORDER BY notifications.postid DESC;
UPDATE notificationrecievers
SET notificationrecievers.status=1
WHERE notificationrecievers.status=0
AND notificationrecievers.recieverid=?
AND
notificationrecievers.notificationid <=
(
SELECT MAX(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)e
)
AND
notificationrecievers.notificationid >=
(
SELECT min(notid) FROM
(
SELECT n.notid FROM user u,notifications n,notificationrecievers nr WHERE
nr.recieverid=? AND u.userid=n.senderid AND nr.notificationid=n.notid ORDER BY n.notid DESC
LIMIT 50 OFFSET ?
)g
);
';
EXECUTE STMT USING #uid,#post,#uid,#rangee,#uid,#rangee,#uid,#uid,#rangee,#uid,#rangee;
When I run this query in the procedure it gives me syntax error.But when I use it directly by giving hard coded values in place of ? than it works fine.Why is this happening? puserid and plimit are the parameters which i pass to this procedure.
This is the error:
Code: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';
UPDATE
notificationrecievers
SET notificationrecievers.st' at line 25