Conditional MySQL Query: FROM table depending of a field - javascript

I have made a gravityform risk assessment quiz. Depending on answers, assigns respondent a profile: aggressive, balanced, conservative. I have 3 MySQL tables with names corresponding to each of those profiles.
This is a single query for 1 of the 3 tables:
$query= "
SELECT value1
, value3
, value4
FROM aggressive
order
by num
LIMIT 7,8
";
This is the gravityform field showing “aggressive, balanced or conservative”:
$profile = slideval($_POST["input_31"]);
How do I write the MySQL query so it selects the right profile and display result in 1 single HTML page, instead of having to create 3 different HTML pages with 3 different queries?
Thanks a lot!

$profile = slideval($_POST["input_31"]);
$query= "SELECT value1,value3,value4 FROM $profile order by num LIMIT 7,8";

You can go with union or unionall
$query = “
SELECT value1,value3,value4 , ‘aggressive’ As tablename FROM aggressive
UNION
SELECT value1,value3,value4 , ‘aggressive’ As tablename FROM balanced
UNION
SELECT value1,value3,value4 , ‘aggressive’ As tablename FROM conservative”;

Related

SQL Statement does not insert the required value to table column

I'm inserting some values to a table using a sql statement. All the values get inserted, except the 'qty' column. When I do an echo for sql statement, it shows the value has been assigned to the sql statement. Table column data type is INT. Can anyone help me to spot the problem?
$it_code = $_POST['id'];
//Prompt user to enter required qty
echo '<script>';
echo 'var qty = prompt("Enter Qty", "");';
echo '</script>';
//Get the item details from item table
$sqlString = "Select * from items where it_code='".$it_code."'";
$objItem = new Allfunctions;
$result = $objItem->retriveData($sqlString);
//Get the selected qty from java script to php variable
$qty = "<script>document.writeln(qty);</script>";
$user_id =$_SESSION['user_id'];
//Insert to orders table
$sqlStringInsert = "INSERT INTO orders(user_id,it_code,qty,status,tr_timestamp) VALUES ('$user_id','$it_code','$qty','PENDING',CURRENT_TIMESTAMP())";
echo $sqlStringInsert;
$objItem->addToTable($sqlStringInsert,'Succsessfully added.','Error adding'); // This is a custom built method to insert data in to a table by taking the sql statement as the parameter
Following is the sql statement generated,
Following is the table data. Qty is always 0 eventhood the sql statement had a value at qty column.
Obligatory warning
The code as you have shown it should not be used in production as it is vulnerable to SQL-injection attacks. Preventing this is well covered on this site in other answers.
Answer
The issue is that the value of $qty you are injecting into your SQL is the string "<script>document.writeln(qty);</script>". You just can't see it because you are likely echoing it out to the browser to test it.
Wrap your echoing of the SQL statement in a call to htmlentities() (docs) to see what's actually happening.
Depending on the version and settings, MySQL is very forgiving of bad data being injected to a column. In this case, it sees a string of text being inserted to a numeric column, and just truncates it to 0. See this in action here:
CREATE TABLE Foo (
Id INT,
Qty INT
);
INSERT INTO Foo(Id, Qty) VALUES (1, 'a string of text');
SELECT * FROM Foo; -- returns a row (1, 0)
https://www.db-fiddle.com/f/dEoaYGEyXEjs6ocVBwyyyr/1

Retrieve data from a Card in Oracle Apex

I have a Card Regions which display some of my tables. I want the cards to each redirect to a certain page based on a number (the number labelled has "page_table" is the page number it will redirect on).
Here's the Query of the Cards Region
SELECT table_name,
REPLACE(SUBSTR(table_name, 8),'_','-') AS nom_table, -- here, i remove the "INV_TB_" prefix from my tables
CASE
WHEN table_name = 'INV_TB_BATIMENT' THEN 11
WHEN table_name = 'INV_TB_CATEGORIE' THEN 12
WHEN table_name = 'INV_TB_DEPARTEMENT' THEN 13
WHEN table_name = 'INV_TB_SERVICE' THEN 14
WHEN table_name = 'INV_TB_POSSEDER' THEN 15
WHEN table_name = 'INV_TB_SITUER' THEN 16
WHEN table_name = 'INV_TB_ETAGE_BUREAU' THEN 16 END AS page_table --this is the column where i define the page number for each table
from cat
WHERE table_name LIKE 'INV_TB_%'
AND table_name <> 'INV_TB_AMORTISSEMENT'
AND table_name <> 'INV_TB_ARTICLE_LOGS'
AND table_name <> 'INV_TB_ARTICLE_DASHBOARD'
AND table_name <> 'INV_TB_DOCUMENT'
AND table_name <> 'INV_TB_VILLE'
AND table_name <> 'INV_TB_DASHBOARD'
AND table_name <> 'INV_TB_ARTICLE'
Here's the result :
For each one of them, I want to be able to retrieve the number in the little square on the left :
Which will be used to redirect the user to the specific page in Link and Target of the Cards :
I've thought about using an Hidden Item which will receive the value of the square when I click on the card, maybe using JavaScript or jQuery ? Or is there a more easy way to retrieve the value of the custom column "page_table" based on the card I'm clicking on ?
My last solution is to create a table which will contains the name of the real tables, with the page number in real columns, but I would like to know first if my first idea is possible
Thanks in advance,
Thomas
In the cards region, the substitution syntax for columns is &COLUMN_NAME. so in your case &PAGE_TABLE. should work. Can you give that a try ?

Mixing results from 2 different MySQL queries for a user feed

I want to make a primitive personalized feed in a NodeJS+MySQL website. Now I just select all the posts that have specific tags in them:
SELECT column1, column2...
FROM table
WHERE tags = users_tags
ORDER BY relavance
LIMIT 8;
I want to also throw in a couple of popular posts eg:
SELECT column1, column2...
FROM table
ORDER BY relevance
LIMIT 2;
I don't want to use UNION because I want to retain the ordering from my first select and insert a popular result for every 5th post. Eg.: relevant, relevant, relevant, relevant, popular, relevant...
For now, I've results1.concat(results2) which adds them as the last two, and returned it. Then I had a for loop that would append the to HTML normally for the first 4 and then one from the back for every 5th.
Is there any better solution?
What you could use, is row_number to define the sortorder
SELECT column1,column2
FROM
(SELECT column1,column2,IF(rn = 1, B,D) as sortorder
FROM
(SELECT column1, column2, ROW_NUMBER() OVER(ORDER BY relavance) rn
FROM table1
ORDER BY relavance
LIMIT 2) t1
UNION
SELECT column1,column2,IF(rn < 5, A,C) as sortorder
FROM
(SELECT column1, column2, ROW_NUMBER() OVER(ORDER BY relavance) rn
FROM table1
WHERE tags = users_tags
ORDER BY relavance
LIMIT 8) t2) t3
ORDER BY sortorder
You can use ROW_NUMBER() window function to rank separately the posts with specific tags and the popular posts and then do a conditional sort:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY tags = users_tags ORDER BY relevance) rn
FROM tablename
)
SELECT *
FROM cte
ORDER BY CASE
WHEN tags = users_tags THEN rn + FLOOR((rn - 1) / 4)
ELSE (4 + 1) * rn
END
LIMIT 10;
Change 4 to the number of posts with specific tags that you want in each block.
See a simplified demo.

Query multiple not related tables in SQL

I have more than 50 tables that are not related but all of them have a "Name" field, I want to query "John" and get all Johns in the different tables and store each row in an array (Javascript) for example:
arr['table1']="results if any"
arr["table2"]="results if any".
What I'm doing right now is a for loop for each table:
SELECT * from tablesNameArray[i] WHERE name="John",
but I'm really wondering if there is any other better or "more" correct way to do it.
Thanks
You can do it in a single query using UNION:
SELECT * FROM table1 WHERE name = 'John'
UNION ALL
SELECT * FROM table2 WHERE name = 'John'
UNION ALL
SELECT * FROM table3 WHERE name = 'John'
...
You can construct the query dynamically from the array:
sql = tablesNameArray.map(table => `SELECT * FROM ${table} WHERE name = 'John'`).join(" SELECT ALL ");
You could use joins. See the join docs, MySQL in this case.
Something like this should do it:
SELECT table1.*, table2.*, table3.*
FROM table1
LEFT JOIN table2 ON table1.name = table2.name
LEFT JOIN table3 ON table1.name = table3.name
WHERE table1.name = "John";
A left join will still select from the first table even if the joined table doesn't have a matching row -- you'll get NULL in the second table's selected columns for those rows which didn't match.
However, depending on your requirements, this is possibly no good -- I believe it won't grab rows from table2 or table3 where there's no corresponding row for that user in table1.
As pointed out by #spencer7593 in a comment below, you should probably only do this if you're certain the name column is unique within each table, otherwise you could be generating some ridiculously huge result sets.

Sequalize limit by unique values in column

I have the following database structure:
id (int) | user_id (int) | product_id (int) | data (jsonb)
A combination of the id, user_id and product_id make the primary key. So there can be multiple rows with the same product_id and user_id.
The data column has some JSON containing the following
{ "item": boolean }
The query I need is to select all rows where user_id = x and data-->item = true. This part I can do, but I need to apply a limit. The limit should not restrict the number of rows that are returned, but instead restrict the number of DISTINCT product_ids that are returned. So if I apply a limit of 10 I could have 50 rows returned if each of the unique products have 5 rows belonging to the user_id and and item true.
This is what I have so far but it makes no attempt at this limit. I believe I may need a subquery or GROUPBY but I'm not sure how to achieve this in Sequalize.
return this.myModel.findAll({
where: {
user_id: userId,
'data.item': true,
},
});
Any guidance will be much appreciated! Thanks
A query to do this involves JOINing a subquery:
SELECT m.*
FROM my_model m
JOIN (
SELECT DISTINCT product_id FROM model LIMIT 10
) n ON n.product_id = m.product_id
WHERE m.user_id = $1 AND (data->>'item')::boolean IS TRUE;
To my knowledge, Sequelize cannot represent this query structure, although inlining the subquery as a literal may be possible. But it looks like you'll be running at least some raw SQL one way or the other.

Categories