I need a small hint... I've got 2 Tables.
Table 1 gets data from an external api.
Table 2 is static.
Table 1: data
id name status ratio import_id
1 Test online 3 1
2 Tee online 2 1
3 Test online 1 2
4 Tee online 0.01 2
5 Test offline 4 3
6 Teee online 3 3
7 Teet online 1 3
Table 2: names
id name tag active
1 Test t1 1
2 Tee t2 1
3 Teee t3 0
4 Teet t4 1
I want to have the ID from the table names (to write into another table and execute a cronjob)
Explanation Table 1:
id - AI
name - just the name
status - if the entry is active
ratio - the main select
import_id - every 10 minutes I do import from json (~40 entries)
what i've got:
$result = mysql_query("
SELECT
import_id
FROM
data
ORDER BY id DESC LIMIT 1");
while($raw = mysql_fetch_object($result))
{
$the_id = $raw->import_id;
echo $the_id;
}
Now I've got the ID and try to get the latest entry (import_id) with the highest ratio:
$c_result = mysql_query("
SELECT
name, active, ratio, import_id
FROM
data
WHERE
active = '1' AND import_id = '$the_id'
ORDER BY
ratio DESC LIMIT 1");
while($chosen = mysql_fetch_object($c_result))
{
$the_c = $chosen->name;
echo $the_c;
}
That works flawless.
But it is possible that one of the 40 entries provided by api is not in my table "names" or it is not marked as "active".
But I only want the names.id of
the name with the highest ratio
which is in my table "names"
which is marked as active in "names"
and the data.status is online
which is from the latest import (highest import_id)
and write it to another table.
I thought about a LEFT JOIN but if the names.name is not in the table "names" i just get an empty result.
Have you got a hint in the right direction?
SELECT d.name, active, ratio, import_id
FROM data d
JOIN names n ON d.name = n.name
WHERE import_id = (SELECT import_id
FROM data
ORDER BY id DESC
LIMIT 1)
AND d.status = 'online'
AND n.active = 1
ORDER BY ratio DESC
LIMIT 1
DEMO
Related
Music table
id | title
1 Rap God
2 Blank Space
3 Bad Blood
4 Speedom
5 Hit 'em up
Like table
u_id | m_id
1 1
1 2
1 4
1 5
2 3
2 4
2 5
3 1
3 5
4 1
4 2
4 5
Now if someone visits music with m_id = 1
Then the output might be like
m_id
5
2
4
To explain this a bit...
As m_id = 1 is liked by users -> {1,3,4} which in turn likes ->{2,4,5} musics. Since m_id=5 is liked by max number of users its first followed by m_id = 2 and m_id = 4.
My Try
I queried the users who liked m_id = 1
SELECT u_id FROM likes WHERE m_id =1
Then i stored in in an array and selected each of their likes and
arranged them in desc order of count.
But it is a very slow and long process is there any way i can do this ?
p.s I have heard of Association Rules and Bayesian theorem can be user to achieve this. But can anyone help me out with an example ?
You can JOIN back on the Like table and do something like this.
SELECT also_like.m_id, COUNT(also_like.m_id)
FROM [like] AS did_like
JOIN [like] AS also_like ON
also_like.u_id = did_like.u_id
AND also_like.m_id != did_like.m_id
WHERE did_like.m_id = 1
GROUP BY also_like.m_id
ORDER BY COUNT(also_like.m_id)
Essentially you are getting a list of users who liked an item then getting a complete list of those user's likes excluding the item they just liked.
You can then add a HAVING clause or LIMIT to filter things down a bit more.
using a subquery ...
SELECT m_id, count(u_id) as Rank FROM `like`
WHERE u_id in
(
SELECT u_id
FROM `like`
WHERE m_id = 1
)
AND m_id <> 1
GROUP BY m_id
ORDER BY Rank DESC
and optionally
LIMIT 0, 10
or how many "alsolikes" you want to display
I have a two MYSQL tables:
Table-1
id catid title user_rating
123 8 title-one 3
321 8 title-two 5
and
Table-2
listing_id title user_rating
123 title-one 3
321 title-two 5
Plus, I have this query that calculates the current rank of each "title" based on "user_rating".
SELECT
MAX(x.rank) AS rank
FROM
(SELECT
a.id,
a.catid,
a.title,
b.listing_id,
#rank:=#rank + 1 AS rank
FROM
`table-1` a
INNER JOIN `table-2` b ON a.id = b.listing_id
CROSS JOIN (SELECT #rank:=0) r
WHERE
catid = '8'
ORDER BY user_rating DESC) x
WHERE
id = 123
Now, my issue: I want to calculate the difference in "ranking" (rank) when I update the "user_rating" value.
Please, note: the "user_rating" value is updated by a php script that allow users to vote for a specific content (range 1 to 5, step 0.5).
What's the best way to get the difference between the "previous rank" and "current rank" after the update?
Thanks in advance to all.
I have a database which contains some picture data and a linking table. The tables are build-up like this:
---pictures---
picid Lat Lon
1 5 6
2 7 31
3 31 43
4 -3 35
---user2pictures---
picid userid vote
1 1 1
1 2 1
3 1 -1
3 2 1
4 2 -1
The table pictures contains a picture id and some data about the image, the table user2votes contains vote data from the images. Each user is able to vote on images, but they can only vote 1 time, so the vote will be either 1 (like) or -1 (dislike).
I want to select everything from the pictures table from pictures which have the highest number of votes. Pseudoquery which might explain better what I want:
SELECT * FROM pictures WHERE (SELECT MAX(SUM(vote)) FROM user2pictures LIMIT 12
In this example picture 1 would return at the top, picture 3 would follow and picture 4 as the last one. I really don't know how to solve this, some help in the right direction would be very much appreciated!
Thanks!
The answer is to JOIN the tables, SUM the votes, and ORDER high-to-low by the sum of the votes
SELECT pictures.*, SUM(user2pictures.vote) AS VoteTotal
FROM pictures
JOIN user2pictures ON pictures.picid = user2pictures.picid
GROUP BY pictures.picid
ORDER BY VoteTotal DESC
LIMIT 12
try this
select p.`picid`, `Lat`, `Lon` from pictures p
inner join user2pictures u2p
on p.picid = u2p.picid
group by u2p.picid
order by sum(vote) desc
limit 12
DEMO
I'll assume that you also want to show the pictures with no votes. So, you can try this:
select
p.picId, sum(v.vote) as votes
from
pictures as p
left join user2pictures as v on p.picId = v.picId
group by
p.picId
order by
sum(v.vote) desc
limit 12;
The left join is what lets you show the pictures with no votes (the column votes will have the value 0)
Hope this helps
:-)
I have this script, which find a users position taken from the number of credits.
It all works, but i have a little problem. If two users have the same credits, both of them will be on the same position.
Can I do, so if there are more users with same credits, then the system need to order by the users ID and out from that give them a position?
This is my code so far:
$sql = "SELECT COUNT(*) + 1 AS `number`
FROM `users`
WHERE `penge` >
(SELECT `penge` FROM `users`
WHERE `facebook_id` = ".$facebook_uid.")";
$query_rang = $this->db->query($sql);
So if i have this:
ID -------- Credits
1 -------- 100
2 -------- 100
3 -------- 120
Then the rank list should be like this:
Number 1 is user with ID 3
Number 2 is user with ID 1
Number 3 is user with ID 2
ORDER BY credits DESC, id ASC. This will sort by credits and break ties with the id.
UPDATE
I understand now that you want the ranking information for the user, not just to sort the users by credits and ids. This will give you the complete list of users and their rankings:
SELECT #rank:=#rank+1 AS rank, users.id, users.facebook_id FROM users, (SELECT #rank:=0) dummy ORDER BY penge DESC, id ASC
Getting the row number is the tricky bit solved by this blog post:
http://jimmod.com/blog/2008/09/displaying-row-number-rownum-in-mysql/
$sql = "SELECT COUNT(*) + 1 AS `number` FROM `users` WHERE `penge` > (SELECT `penge` FROM `users` WHERE `facebook_id` = ".$facebook_uid.") ORDER BY COUNT(*) + 1 desc, users.ID";
$query_rang = $this->db->query($sql);
Later EDIT:
I don't understand why you still have the same results....
I made a quick test. I have created a table:
Test: ID (Integer) and No (Integer)
I have inserted some values:
id no
1 1
1 1
1 1
2 1
3 1
4 1
4 1
5 1
Now, if I run:
SELECT
id, COUNT(*) + 1 AS `number`
FROM
test
GROUP BY
id
I get:
id number
1 4
2 2
3 2
4 3
5 2
But if I add ORDER BY:
SELECT
id, COUNT(*) + 1 AS `number`
FROM
test
GROUP BY
id
ORDER BY
count(*) desc, id
then I get:
id number
1 4
4 3
2 2
3 2
5 2
I have written a query which returns all records with some many-to-many joins correctly for the entire set or an individual article using WHERE a.id = ?
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id
LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id
LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id
LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
BUT!
I've hit a brick wall trying to work out how to limit the articles to a specific number of IDs, for working with pagination.
I'm ideally trying to use as simple and clear SQL statements as possible because I'm using the codeigniter framework with their active record class.
http://codeigniter.com/user_guide/database/active_record.html
Would really appreciate some help as I don't want to revert to using multiple queries for this as I've tried to reduce it down to a single query for database efficiency.
Have search around and tried some alternatives but nothing seems to work. Many thanks!
For example the results I return are like this
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
2 test 2 2 1 1
2 test 2 1 2 1
2 test 2 1 1 2
2 test 2 5 1 1
2 test 2 8 1 1
2 test 2 1 4 1
2 test 2 1 4 2
I need the results like this so that I can create sub-arrays in the php like this:
$articles = $query->result_array();
$output = array();
foreach ($articles as $article) {
// set up article details
$article_id = $article['id'];
// add article details
$output[$article_id]['article_id'] = $article_id;
$output[$article_id]['date_added'] = $article['date_added'];
$output[$article_id]['title'] = $article['title'];
$output[$article_id]['content'] = $article['content'];
// set up people details and add people array with details if exists
if (isset($article['person_id'])) {
$person_id = $article['person_id'];
$output[$article_id]['people'][$person_id]['person_id'] = $person_id;
$output[$article_id]['people'][$person_id]['lastname'] = $article['lastname'];
$output[$article_id]['people'][$person_id]['firstname'] = $article['firstname'];
}
// set up organizations details and add organizations array with details if exists
if (isset($article['organization_id'])) {
$organization_id = $article['organization_id'];
$output[$article_id]['organizations'][$organization_id]['organization_id'] = $organization_id;
$output[$article_id]['organizations'][$organization_id]['organization_name'] = $article['organization_name'];
}
// set up categories details and add categories array with details if exists
if (isset($article['category_id'])) {
$category_id = $article['category_id'];
$output[$article_id]['categories'][$category_id]['category_id'] = $category_id;
$output[$article_id]['categories'][$category_id]['category_name'] = $article['category_name'];
}
}
But if I just use LIMIT (with offset etc) 1
the results I get are
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
instead of
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
which is my desired result.
OK, so finally I worked out how it is possible.
Thought i'd include it here in case anyone else has the same problem.
Changing this line
FROM articles AS a
to this
FROM (SELECT * FROM articles LIMIT 5,3) AS a
does what I wanted.
So, why don't you use OFFSET 0,10 and LIMIT *number_of_results* in the SQL Query? (if I understood the question)
Specific number of IDs... WHERE ID IN (2,4,6,8)... ?
Are you using codeigniter's pagination?
http://codeigniter.com/user_guide/libraries/pagination.html
You can easily limit the number of records that are being returned using the MySQL LIMIT clause. This can be achieved like the following with your sample query.
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
LIMIT 10
Where 10 is the number of records you wish to display. The MySQL LIMIT clause allows you to specify a limit of the number of records and an initial offset. Like so:
LIMIT <offset>,<limit>
In your case <offset> would be the current page * the number of records on a page. <limit> would be the number of records you would like to display per page.