for example:
my products best sort string is "'8207,17631,16717,18545,9062,17469,17246,17750"
this string is posted from php , I dont want to store them in datebase. I want to query datas from mysql and left join a temp table then sort by the temp table'sort.
how can I get this temp table from a string ?
my codes seems will be like that bellow:(wrong codes)
select
p.products_id
from
(
select '18207,17631,16717,18545,9062,17469,17246,17750' as products_id
) as p
order by p.sort
Your best approach could be - to use UNION for generating row set from string. This, however, will require joining your string in your application, like this:
$string = '18207,17631,16717,18545,9062,17469,17246,17750';
$id = 0;
$sql = join(' UNION ALL '.PHP_EOL, array_map(function($item) use (&$id)
{
return 'SELECT '.(++$id).' AS sort, "'.$item.'" AS products_id';
}, explode(',', $string)));
-end result will be like:
SELECT 1 AS sort, "18207" AS products_id UNION ALL
SELECT 2 AS sort, "17631" AS products_id UNION ALL
SELECT 3 AS sort, "16717" AS products_id UNION ALL
SELECT 4 AS sort, "18545" AS products_id UNION ALL
SELECT 5 AS sort, "9062" AS products_id UNION ALL
SELECT 6 AS sort, "17469" AS products_id UNION ALL
SELECT 7 AS sort, "17246" AS products_id UNION ALL
SELECT 8 AS sort, "17750" AS products_id
However, if you want to do that in SQL - that will not be easy, since MySQL doesn't supports sequences - and, therefore, you'll need to use some tricks to produce desired rows set. There's a way to generate N consecutive numbers with:
SELECT id+1
FROM
(SELECT
(two_1.id + two_2.id + two_4.id +
two_8.id + two_16.id) AS id
FROM
(SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1
CROSS JOIN (SELECT 0 id UNION ALL SELECT 2 id) AS two_2
CROSS JOIN (SELECT 0 id UNION ALL SELECT 4 id) AS two_4
CROSS JOIN (SELECT 0 id UNION ALL SELECT 8 id) AS two_8
CROSS JOIN (SELECT 0 id UNION ALL SELECT 16 id) AS two_16
) AS init
LIMIT 10
-this will result in 10 numbers 1..10 (check this fiddle). Using this, you can get your end result:
SELECT
ELT(id+1, 18207,17631,16717,18545,9062,17469,17246,17750) AS products_id,
id+1 AS sort
FROM
(SELECT
(two_1.id + two_2.id + two_4.id +
two_8.id + two_16.id) AS id
FROM
(SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1
CROSS JOIN (SELECT 0 id UNION ALL SELECT 2 id) AS two_2
CROSS JOIN (SELECT 0 id UNION ALL SELECT 4 id) AS two_4
CROSS JOIN (SELECT 0 id UNION ALL SELECT 8 id) AS two_8
CROSS JOIN (SELECT 0 id UNION ALL SELECT 16 id) AS two_16
) AS init
HAVING
products_id IS NOT NULL
-check this fiddle. However, this may be slow and I recommend you to use your application layer to build desired SQL.
something like this? use UNION to generate inline view. this can be generated by Client side.
SELECT *
FROM
(
SELECT '18207' AS products_id, 1 as sort
UNION
SELECT '17631' AS products_id, 2 as sort
UNION
SELECT '16717' AS products_id, 3 as sort
UNION
SELECT '18545' AS products_id, 4 as sort
UNION
SELECT '9062' AS products_id, 5 as sort
) x JOIN tbl x.products_id = tbl.products_id
ORDER BY sort
Related
I would like to know if is possible to return the results from UNION grouped by their alias.
For instance:
(SELECT * FROM table1) AS first
UNION
(SELECT * FROM table2) AS second
so that the result is:
first = contains all table1 rows
second = contains all table2 rows
Practically i want an associative array like this:
[]=>[
'first'=>[table1 results],
'second'=>[table2 results]
]
I tried it but doesn't work. Maybe i'm doing it bad.
Can this be done with a single query or i've to do 2 separated queries.
Thanks.
You cannot do this with union because it removes duplicates. You can with union all.
One way is:
SELECT t.*, 0 as which FROM table1 t
UNION ALL
SELECT t.*, 1 FROM table2 t
ORDER BY which;
If you don't want to see which in the output, use a subquery:
select . . .
from (select t.*, 0 as which from table1 t union all
select t.*, 1 as which from table1 t
) t
order by which;
I have a table looking like this:
ID quote_no version
------------------------
1 123 1
2 123 2
3 123 1
4 123 2
5 321 1
6 321 1
I would like to select the latest version of each quote, and if theres multiple records of that version i would like to get the row with the highest ID.
(in this case the query should produce the following result):
ID quote_no version
------------------------
4 123 2
6 321 1
How could I do that in a query?
You can approach this with a not exists clause:
select t.*
from table t
where not exists (select 1
from table t2
where t2.quote_no = t.quote_no and
(t2.version > t.version or
t2.version = t.version and t2.id > t.id
)
);
If you just want the one with the highest id (which is also consistent with your results), you can do:
select t.*
from table t join
(select quote_no, max(id) as maxid
from table t
group by quote_no
) tt
on t.id = tt.maxid;
I would write a subquery that gets the largest version for each quote_no, like this:
SELECT quote_no, MAX(version) AS maxVersion
FROM myTable
GROUP BY quote_no;
And you can join that with your original table, and use another MAX() function to get the largest id:
SELECT MAX(m.id), m.quote_no, mt.maxVersion
FROM myTable m
JOIN(
SELECT quote_no, MAX(version) AS maxVersion
FROM myTable
GROUP BY quote_no) mt ON mt.quote_no = m.quote_no AND mt.maxVersion = m.version
GROUP BY m.quote_no;
Works fine in SQL Fiddle.
The latest X records per group is a tough problem in MySQL, except when X is 1 as in your case. You can do it like this. For each quote, join all rows that have the same quote_no, but a greater version., or the same version but with a larger ID. Then you can apply a filter to only keep those rows that don't have a greater version:
SELECT
t1.*
FROM
YourTable t1
LEFT JOIN YourTable t2 ON
t2.quote_no = t1.quote_no AND -- Quote must match anyway
( t2.version > t1.version OR -- Version must be larger
( t2.version = t1.version AND -- Or if version is the same...
t2.ID > t1.ID ) -- ID must be larger.
WHERE
t2.quote_no IS NULL
Try something like that :
SELECT t2.*
FROM QuoteTable t2
JOIN (SELECT
MAX(ID) AS t1.LatestId,
quote_no
FROM QuoteTable t1
GROUP BY quote_no)
ON t2.id = t1.LatestId;
EDIT : the Parent SELECT statement prevents version number error.
I have the following details in MySQL as
user_id follow_user_id
1 2,3,3,3,3
5 1,2,3,3,3,3
6 1,2,3,3,3,3
i write the following code to get the unique code as follow:
SELECT LENGTH( follow_user_id ) - LENGTH( REPLACE( follow_user_id, ',', '' ) ) +1 AS no_of_follow FROM follow WHERE user_id =1;
But it provide the result:6
I need exactly unique rows: i.e:4
Apart from DB design questions you could use in PHP after fetching the row to $result:
count(array_unique(explode(",",$result["follow_user_id")));
$query="SELECT follow_user_id FROM follow WHERE user_id ='".$_POST['user_id']."' "; $query_run=mysql_query($query); $row= mysql_fetch_assoc($query_run);
$count= count(array_unique(explode(",",$row['follow_user_id'])));
$count;
This is better and faster ;)
count(array_flip(explode(",", $result["follow_user_id")));
Or doing it in SQL:-
SELECT COUNT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(follow_user_id, ',', units.i + tens.i * 10), ',', -1) AS col1)
FROM sometable
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)units
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)tens
WHERE user_id = 1
(copes with up to 100 comma separated values).
But this would be so much easier with a properly normalised database design
I've gotten my database set up for my website and I'm a little baffled on how I should write the SQL query to display the information how I want it.
Here's an image of how my database is setup and an example of how I want to display it:
Here's the SQL query I wrote to get the information (Im open to writing a better solution)
SELECT * FROM drinks_category, drinks_lookup, drinks
WHERE drinks.drink_id = drinks_lookup.drink_id
AND drinks_lookup.drinks_category_id = drinks_category.drinks_category_id
This gets me all the info but I'm not sure how to write the output to get it to show how i want.
One solution is to order by category:
SELECT *
FROM drinks_category, drinks_lookup, drinks
WHERE drinks.drink_id = drinks_lookup.drink_id
AND drinks_lookup.drinks_category_id = drinks_category.drinks_category_id
ORDER BY drinks_category.drink_category_title
With that, you can loop in PHP, and output a new header whenever a new category appears. Something like this:
<?php
$last_category = 0;
foreach($data as $row) {
if($row['drinks_category_id'] != $last_category) {
echo '<h1>' . $row['drink_category_title'] . '</h1>';
}
echo '<div>' . $row['drinks_name'] . '</div>';
$last_category = $row['drinks_category_id'];
}
?>
You should probably use nested html lists instead of the markup above, but this should get you started.
Since you use PHP, the best way to do this is to use an outer-inner-query loop:
Outer query: SELECT * FROM drings_category, then loop:
Display drink_category_title
Use drink_category_id as $ID for SELECT drinks.drink_name FROM drinks INNER JOIN drinks_lookup ON drinks.drink_id=drinks_lookup.drink_id WHERE drinks_lookup.drink_category_id=$ID
Loop and display drinks
Hideously over complicated way to do it in a single sql statement for 3 fixed columns, coping with up to 1000 drinks in each category.
SELECT DrinkCategory1Subselect.drink_name AS 'Drink Category Title', DrinkCategory2Subselect.drink_name AS 'Drink Category Title 2', DrinkCategory3Subselect.drink_name AS 'Drink Category Title 3'
FROM (SELECT a.i+b.i*10+c.1*100 AS aCounter
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) b,
(SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) c) Deriv1
INNER JOIN (SELECT c.drink_name,
#Counter := #Counter + 1 AS aCounter
FROM drinks_category a
INNER JOIN drinks_lookup b ON a.drink_category_id = b.drink_category_id
INNER JOIN drinks c ON b.drink_id = c.drink_id
CROSS JOIN (SELECT #Counter:=0) NothingUseful
WHERE a.drink_category_id = 1
ORDER BY c.drink_id) DrinkCategory1Subselect
ON DrinkCategory1Subselect.aCounter = Deriv1.aCounter
INNER JOIN (SELECT c.drink_name,
#Counter := #Counter + 1 AS aCounter
FROM drinks_category a
INNER JOIN drinks_lookup b ON a.drink_category_id = b.drink_category_id
INNER JOIN drinks c ON b.drink_id = c.drink_id
CROSS JOIN (SELECT #Counter:=0) NothingUseful
WHERE a.drink_category_id = 2
ORDER BY c.drink_id) DrinkCategory2Subselect
ON DrinkCategory2Subselect.aCounter = Deriv1.aCounter
INNER JOIN (SELECT c.drink_name,
#Counter := #Counter + 1 AS aCounter
FROM drinks_category a
INNER JOIN drinks_lookup b ON a.drink_category_id = b.drink_category_id
INNER JOIN drinks c ON b.drink_id = c.drink_id
CROSS JOIN (SELECT #Counter:=0) NothingUseful
WHERE a.drink_category_id = 3
ORDER BY c.drink_id) DrinkCategory3Subselect
ON DrinkCategory3Subselect.aCounter = Deriv1.aCounter
WHERE DrinkCategory1Subselect.drink_name IS NOT NULL
OR DrinkCategory2Subselect.drink_name IS NOT NULL
OR DrinkCategory3Subselect.drink_name IS NOT NULL
ORDER BY Deriv1.aCounter
Not tested. Better to do the formatting in php, but was bored
Is it possible to add and multiply the count of different tables where the id is the same?
Imagine:
Table_1 Table_2 Table_3
id id id
1 1 1
1 2 2
2 2 3
3 2 3
3 2 3
3 3 3
So that the end result would be this table with 2 columns:
id (COUNT(Table_1.id) + 2*COUNT(Table_2.id) + 3*COUNT(Table_3.id))
1 7
2 12
3 17
I don't know if I understood you correctly but give this a try,
SELECT a.ID,
a.aa + (2 * b.bb) + (3 * c.cc)
FROM
(
SELECT ID, COUNT(*) aa
FROM table1
GROUP BY ID
) a LEFT JOIN
(
SELECT ID, COUNT(*) bb
FROM table2
GROUP BY ID
) b ON a.ID = b.ID
LEFT JOIN
(
SELECT ID, COUNT(*) cc
FROM table3
GROUP BY ID
) c ON a.ID = c.ID
SQLFiddle Demo
SELECT id, counts_1.number + 2 * counts_2.number + 3 * counts_3.number
FROM
(SELECT id, COUNT(*) AS number FROM Table_1 GROUP BY id) AS counts_1
JOIN
(SELECT id, COUNT(*) AS number FROM Table_2 GROUP BY id) AS counts_2 USING (id)
JOIN
(SELECT id, COUNT(*) AS number FROM Table_3 GROUP BY id) AS counts_3 USING (id)
Note that this solution requires that every id exists at least once in each of the tables, otherwise it will be left out of the result. Changing this would require a FULL OUTER JOIN that MySQL is incapable of. There are ways around that limitation, though.