This question already has answers here:
MySQL query to return results in specific order without order by
(5 answers)
Closed 8 years ago.
I have a simple mysql query like this.
SELECT name,cat_id FROM table WHERE cat_id IN (67,65,66);
But I am having a problem getting the results back in a proper order.
[0] => Array
(
[cat_name] => name 1
[cat_id] => 65
)
[1] => Array
(
[cat_name] => name 2
[cat_id] => 66
)
[2] => Array
(
[cat_name] => name 3
[cat_id] => 67
)
I need them to be ordered by the cat_id that was put into the sql statement.
67, then 65 and then 66.
But it always wants to return results by order 65, 66, 67.
Can someone help me figure this out? I rather get the results in the correct order, than use php to manipulate the array.
SELECT
name,
cat_id
FROM table
WHERE cat_id IN (67)
order by cat_id asc;
UNION
SELECT
name,
cat_id
FROM table
WHERE cat_id IN (65,66)
order by cat_id asc;
Related
I have two tables
Meetings:
m_id ProjectName
1 Test
2 Test2
Meeting_next:
id fk_m_id Meetingdate status
1 1 9-1-2018 0
1 1 10-1-2018 0
1 1 13-1-2018 1
I want to join this two tables when I left join it I will get duplicate value
Expected output
Array
(
[0] => Array
(
[m_id] => 1
[ProjectName] => test
[meetingDate] =>13-1-2018
)
[1] => Array
(
[m_id] => 2
[ProjectName] => test2
[meetingDate] =>
)
)
I tried -
select * from meetings left join meeting_next on meetings.m_id= meeting_next.fk_m_id where meeting_next.status=1 order by m_id desc
myOutput:
Array
(
[0] => Array
(
[m_id] => 1
[ProjectName] => test
[meetingDate] =>13-1-2018
) )
Bad luck I got only first Project name. I need second too. Please help me. Any help would be appreciated.
Your WHERE condition filters the number of rows to only the row of the first project.
If you want to show both projects, even if there are no meetings with status 1, you need to move the condition to the join condition:
select *
from meetings
left join meeting_next
on meetings.m_id= meeting_next.fk_m_id
and meeting_next.status=1
order by m_id desc
Now you will get all rows from meetings with only the matching entries from meeting_next.
on my ratings table for my software i have 4 fields.
id autoincrement
rvid vendor id
ratedate date of rating
rating the actual numeric rating
I have done alot with it over the last few months but this time im stumped and i cant get a clear picture in my head of the best way to do this. What i am trying to do is find out if the vendor has had 3 low 'consecutive' ratings. If their last three ratings have been < 3 then i want to flag them.
I have been playing with this for a few hours now so i thought i would ask (not for the answer) but for some path direction just to push me forward, im stuck in thought going in circles here.
I have tried GROUP BY and several ORDER BY but those attempts did not go well and so i am wondering if this is not a mysql answer but a php answer. In other words maybe i just need to take what i have so far and just move to the php side of things via usort and the like and do it that way.
Here is what i have so far i did select id as well at first thinking that was the best way to get the last consective but then i had a small breakthrough that if they have had 3 in a row the id does not matter, so i took it out of the query.
$sql = "SELECT `rvid`, `rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `rvid` DESC";
which give me this
Array
(
[0] => Array
(
[rvid] => 7
[rating] => 2
)
[1] => Array
(
[rvid] => 5
[rating] => 1
)
[2] => Array
(
[rvid] => 5
[rating] => 0
)
[3] => Array
(
[rvid] => 5
[rating] => 3
)
)
this is just just samples i tossed in the fields, and there are only 4 rows here where as in live it will be tons of rows. But basically this tells me that these are the vendors that have low ratings in the table. And that is where i get stumpted. I can only do one sort in the query so that is why i am thinking that i need to take this and move to the php side to finish it off.
I think i need to sort the elements by rvid with php first i think, and then see if three elements in a row are the same vender (rvid).
Hope that makes sense. My brain hurts lol...
update - here is all of the table data using *
Array
(
[0] => Array
(
[id] => 7
[rvid] => 7
[ratedate] => 2016-05-01
[rating] => 2
)
[1] => Array
(
[id] => 8
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 1
)
[2] => Array
(
[id] => 6
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 0
)
[3] => Array
(
[id] => 5
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 3
)
)
Here's one way you can begin approaching this - completely in SQL:
Get the last rating for the vendor. ORDER BY date DESC, limit 1.
Get the second to last rating for the vendor. ORDER BY date DESC, limit 1, OFFSET 1.
Then write a query that does a LEFT join of the first two tables. You will have a dataset that has three columns:
vendor id
last rating
second to last rating
Then you can write an expression that says "if column1 is <3 and column2 < 3, then this new column is true"
You should be able to extend this to three columns relatively easily.
Here is what a came up with to solve this riddle. I think explaining it on here helped as well as Alex also helped as he keyed my brain on using the date. I first started looking at using if statment inside of the query and actually that got my brain out of the box and then it hit me what to do.
It is not perfect and certainly could use some trimming to reduce the code, but i understand it and it seems to work, so that is par for me on this course.
the query...
$sql = "SELECT `rvid`, `ratedate`,`rating` FROM `vendor_ratings_archive` WHERE `rating` <= '3' ORDER BY `ratedate`, `rvid` DESC";
which gives me this
Array
(
[0] => Array
(
[rvid] => 7
[ratedate] => 2016-05-01
[rating] => 2
)
[1] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 1
)
[2] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 0
)
[3] => Array
(
[rvid] => 5
[ratedate] => 2016-05-01
[rating] => 3
)
)
notice how vendor (rvid) 5 is grouped together which is an added plus.
next a simple foreach to load a new array
foreach($results as $yield)
{
$rvidarray[] = $yield['rvid'];
}//close foreach
which gives me this
Array
(
[0] => 7
[1] => 5
[2] => 5
[3] => 5
)
then we count the array values to group dups
$rvidcounter = array_count_values($rvidarray);
which results in this
Array(
[7] => 1
[5] => 3
)
so now vender 7 as 1 low score and vendor 5 has 3 low scores and since they were already sorted by date i know that its consecutive. Well it sounds good anyway lol ")
then we create our final array with another foreach
foreach($rvidcounter as $key => $value)
{
//anything 3 or over is your watchlist
if($value > 2)
{
$watchlist[] = $key; //rvid number stored
}
}//close foreach
which gives me this
Array
(
[0] => 5
)
this was all done in a service function. So the final deal is everyone in this array has over 3 consecutive low ratings and then i just use a returned array back in my normal php process file and grab the name of each vender by id and pass that to the html and print out the list.
done...
please feel free to improve on this if you like. I may or may not use it because the above code makes sense to me. Something more complicated may not make sense to me 6 mos from now lol But it would be interesting to see what someone comes up with to shorten the process a bit.
Thanks so much and Happy Coding !!!!!
Dave :)
You could do it in SQL like that:
SET #rvid = -1;
SELECT DISTINCT rvid FROM
(
SELECT
rvid,
#neg := rating<3, /* 0 or 1 for addition in next line */
#count := IF(#rvid <> rvid , #neg, #count+#neg) AS `count`, /* set or add */
#rvid := rvid /* remember last row */
FROM
testdb.venrate
ORDER BY
rvid, datetime desc
) subq
WHERE count>=3
;
You set a variable to a non existing id. In each chronologically sorted row you check if rating is too low, that results in 1 (too low) or 0 (ok). If rvid is not equal to the last rvid, it means a new vender section is beginning. On begin of section set the value 0 or 1, else add this value. Finally store the current row's rvid for comparison in next row process.
The code above is looking for 3 consecutive low ratings (low means a value less than 3) over all the time.
A small modification checks if all the latest 3 ratings has been equal to or less than 3:
SET #rvid = -1;
SELECT DISTINCT
rvid
FROM
(
SELECT
rvid,
#high_found := rating>3 OR (#rvid = rvid AND #high_found) unflag,
#count := IF(#rvid <> rvid , 1, #count+1) AS `count`,
#rvid := rvid /* remember last row */
FROM
testdb.venrate
ORDER BY
rvid, datetime desc
) subq
WHERE count=3 AND NOT unflag
;
I’ve seen the following question on StackOverflow, Intelligent MySQL GROUP BY for Activity Streams posted by Christian Owens 12/12/12.
So I decided to try out the same approach, make two tables similar to those of his. And then I pretty much copied his query which I do understand.
This is what I get out from my sandbox:
Array
(
[0] => Array
(
[id] => 0
[user_id] => 1
[action] => published_post
[object_id] => 776286559146635
[object_type] => post
[stream_date] => 2015-11-24 12:28:09
[rows_in_group] => 1
[in_collection] => 0
)
)
I am curious, since looking at the results in Owens question, I am not able to fully get something, and does he perform additional queries to grab the actual metadata? And if yes, does this mean that one can do it from that single query or does one need to run different optimized sub-queries and then loop through the arrays of data to render the stream itself.
Thanks a lot in advanced.
Array
(
[0] => Array
(
[id] => 0
[user_id] => 1
[fullname] => David Anderson
[action] => hearted
[object_id] => array (
[id] => 3438983
[title] => Grand Theft Auto
[Category] => Games
)
[object_type] => product
[stream_date] => 2015-11-24 12:28:09
[rows_in_group] => 1
[in_collection] => 1
)
)
In "pseudo" code you need something like this
$result = $pdo->query('
SELECT stream.*,
object.*,
COUNT(stream.id) AS rows_in_group,
GROUP_CONCAT(stream.id) AS in_collection
FROM stream
INNER JOIN follows ON stream.user_id = follows.following_user
LEFT JOIN object ON stream.object_id = object.id
WHERE follows.user_id = '0'
GROUP BY stream.user_id,
stream.verb,
stream.object_id,
stream.type,
date(stream.stream_date)
ORDER BY stream.stream_date DESC
');
then parse the result and convert it in php
$data = array(); // this will store the end result
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
// here for each row you get the keys and put it in a sub-array
// first copy the selected `object` data into a sub array
$row['object_data']['id'] = $row['object.id'];
$row['object_data']['title'] = $row['object.title'];
// remove the flat selected keys
unset($row['object.id']);
unset($row['object.title']);
...
$data[] = $row; // move to the desired array
}
you should get
Array
(
[0] => Array
(
[id] => 0
[user_id] => 1
[fullname] => David Anderson
[verb] => hearted
[object_data] => array (
[id] => 3438983
[title] => Grand Theft Auto
[Category] => Games
)
[type] => product
[stream_date] => 2015-11-24 12:28:09
[rows_in_group] => 1
[in_collection] => 1
)
)
It seems that you want a query where you can return the data you're actually able to get plus the user fullname and the data related to the object_id.
I think that the best effort would be to include some subqueries in your query to extract these data:
Fullname: something like (SELECT fullname FROM users WHERE id = stream.user_id) AS fullname... or some modified version using the stream.user_id, as we can't identify in your schema where this fullname comes from;
Object Data: something like (SELECT CONCAT_WS(';', id, title, category_name) FROM objects WHERE id = stream.object_id) AS object_data. Just as the fullname, we can't identify in your schema where these object data comes from, but I'm assuming it's an objects table.
One object may have just one title and may have just one category. In this case, the Object Data subquery works great. I don't think an object can have more than one title, but it's possible to have more than one category. In this case, you should GROUP_CONCAT the category names and take one of the two paths:
Replace the category_name in the CONCAT_WS for the GROUP_CONCAT of all categories names;
Select a new column categories (just a name suggestion) with the subquery which GROUP_CONCAT all categories names;
If your tables were like te first two points of my answer, a query like this may select the data, just needing a proper parse (split) in PHP:
SELECT
MAX(stream.id) as id,
stream.user_id,
(select fullname from users where id = stream.user_id) as fullname,
stream.verb,
stream.object_id,
(select concat_ws(';', id, title, category_name) from objects where id = stream.object_id) as object_data,
stream.type,
date(stream.stream_date) as stream_date,
COUNT(stream.id) AS rows_in_group,
GROUP_CONCAT(stream.id) AS in_collection
FROM stream
INNER JOIN follows ON 1=1
AND stream.user_id = follows.following_user
WHERE 1=1
AND follows.user_id = '0'
GROUP BY
stream.user_id,
stream.verb,
stream.object_id,
stream.type,
date(stream.stream_date)
ORDER BY stream.stream_date DESC;
In ANSI SQL you can't reference columns not listed in your GROUP BY, unless they're in aggregate functions. So, I included the id as an aggregation.
I found some similar questions with good answers but i couldnt figure out how to apply this to my specific case. I have a site where users can rate there favorite post from 1-6. Every number is a different category.
Now i need to know the most frequently votes for every single post. So i need to count every post id and than the most frequent values of every post id.
After that i wanna update every result in another table. (dont know how to figure this out right now i'm not that good with Mysql yet).
this are the two columns where i need to know how often every post exist in post_id and what is the most frequently voting number of every single post.
just an example of my table (value = voting)
value | post_id
---------------
3 | 12
1 | 6
4 | 13
2 | 5
6 | 12
5 | 6
i need the output like this to know which post is mostly votet for which category.
post | most voted in this category
---------------
1 | 3
2 | 5
3 | 6
4 | 1
5 | 4
6 | 6
i need this for every post in the table. and than i would need to update every post in another table. i guess i have to do this in a loop.
but im already stuck at the first part.
all i have is this. for the first part.
<?php global $wpdb;
$test = $wpdb->get_results('SELECT posts_id, value, COUNT(posts_id) AS ActionCount
FROM rating_item_entry_value
GROUP BY posts_id
ORDER BY ActionCount DESC');
echo '<pre>';
print_r($test);
echo '</pre>';
and this is the output i get
Array
(
[0] => stdClass Object
(
[posts_id] => 0
[value] => 5
[ActionCount] => 7
)
[1] => stdClass Object
(
[posts_id] => 221
[value] => 3
[ActionCount] => 3
)
[2] => stdClass Object
(
[posts_id] => 197
[value] => 5
[ActionCount] => 2
)
[3] => stdClass Object
(
[posts_id] => 164
[value] => 3
[ActionCount] => 1
)
)
for the example.
I have no idea how to do this better, trying a lot but can't figure it out. does anyone has a good solution how to get the most frequent number for every single id? (and maybe how to safe the results in a variable to update every post in another table within a loop?) thank u so much for any help. regards
most frequently means count aggregation and group by frequency. you can map this to your problem:
select
x.amount,
count(*) as times -- I forgot that row
from
X x
group by
x.amount
order by
count(*) DESC
// edit to you mean that
select
post_id,
value,
count(*)
from
your_table
group by
post_id,
value
order by
count(*) desc
The user can search for something using select and checkbox forms. The data is sent in GET variables.
I'm collected all the possible values in variables and putting it into an array:
$term_taxomony_ids_array = array($term_taxonomy_id_m, $term_taxonomy_id_l, $term_taxonomy_id_t_1, $term_taxonomy_id_t_2, $term_taxonomy_id_t_3, $term_taxonomy_id_t_4, $term_taxonomy_id_t_5, $term_taxonomy_id_t_6, $term_taxonomy_id_t_7, $term_taxonomy_id_t_8);
print_r($term_taxomony_ids_array); would then give
eg:
Array (
[0] => 12
[1] => 14
[2] =>
[3] =>
[4] => 9
[5] =>
[6] => 2
[7] =>
[8] =>
[9] =>
)
How would I make this array simpler but leaving out the empty results altogether (as suggested in a comment)?
I need to find the 'places' in the database who match all the criteria that was selected.
My database table is set up so I have two columns.
1. Object_id 2. term_taxonomy_id.
The term_taxonomy_id are the values in the array.
eg my table looks like this
Object id term_taxonomy_id
2 12
2 3
3 12
3 14
3 9
3 2
4 5
5 9
So only object_id '3' matches all the terms in the array - 12, 14, 9, 2
How would I run a query to find this result?
I'm using a mysql database, phpmyadmin and my site is built on wordpress.
Thanks
Basically:
SELECT objectID, COUNT(term_taxonomy_id) AS cnt
FROM yourtable
WHERE term_taxonomy_id IN (2, 9, 14, 12)
GROUP BY objectID
HAVING cnt = 4
find all the objectIDs that have one or more matching taxonomy IDs, but then return only the object IDs that have FOUR matching taxonomy IDs.
Use IN, Combined with COUNT() and having/GROUP.
$array = array_filter(array_unique($array));
$count = count($array);
$sql = "SELECT id, COUNT(*) FROM table WHERE field IN (" . implode(',', $array) . ") GROUP BY id HAVING COUNT(*) = " . $count;
The SQL might be a bit off (you might have to re-order having and group).