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
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
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 ?
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.
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.
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.