I have a website with different articles. The database structure is like this:
ArticleId | ArticleLocation | ArticleCategory | ArticleTopic
The actual text strings for the columns are in another table so all the columns are populated with numbers (integers)
I want to find related posts, meaning if a user reads an article with ArticleLocation = 1, ArticleCategory= 3 and ArticleTopic = 2, then I want to find top 5 of articles sharing the most of the same column values.
Any ideas of how to do this?
Thanks in advance
Assuming the table is named ArticleTable, try the following:
SELECT *, (
CASE ArticleLocation WHEN :loc THEN 1 ELSE 0 END +
CASE ArticleTopic WHEN :topic THEN 1 ELSE 0 END +
CASE ArticleCategory WHEN :cat THEN 1 ELSE 0 END) AS Relevance
FROM ArticleTable
ORDER BY Relevance DESC
LIMIT 5
with :loc, :topic and :cat set to the relevant values.
Related
I have a table and would like to calculate values. My table:
Table votes
vote type
1 1
-1 1
1 0
-1 0
1 0
-1 1
1 0
Vote: -1 - Down; +1 - Up;
I would like to get something like this:
Count votes up type 1: 1
Count votes down type 1: 2
Votes up type 0: 3
Votes down type 0: 1
Sum votes type 1: 1+(-1)+(-1) = -1
Sum votes type 0: 1+(-1)+1+1 = 2
Is it possible to get results from mysql using single query?
Thanks!
I guess your problem is how to distinct up and down votes here.
You want to group by type (which sounds like a vote/poll ID) and then just pick up and down votes. It can be done using CASE or IF in combination with COUNT or SUM.
COUNT does not count NULL values so I suggest to wrap two COUNTs in IFs.
SELECT
type,
COUNT(IF(vote = -1, TRUE, NULL)) AS down,
COUNT(IF(vote = 1, TRUE, NULL)) AS up
FROM votes
GROUP BY type
SQL Fiddle: http://sqlfiddle.com/#!2/36008/1/0
you can write
select count(*) from table where type = 1 and vote = -1
select count(*) from table where type = 1 and vote = 1
the above will give you the result count which you want .
This will work
select sum(vote),type from table group by type;
assume I have a table that contain a column named post_id and it has the result like
1
1
1
2
2
3
1
1
I want to loop through all the records and count how many times they exist. What I could thought of is
by while loop
if(result[] = 1){$1++}, but the problem is the value of record is not fixed, it can be 9999..
I'd tried
while ($something= $item->fetch_array()) {
while($test[] = $something['post_id'] > 0){
//logic here
}
}
select post_id, count(*)
from table
group by post_id
This is something you can do in SQL. I believe it would be the following:
SELECT post_id, COUNT(*) FROM tablename GROUP BY post_id;
This will return, for each post_id in the table, that post_id and the count of rows with that post_id.
Have you try this.
Assume:
Table one
**Table one**
Column1
1
1
1
2
2
3
1
1
You can use this query to count it.
SELECT one.column1, COUNT(two.column1) FROM one as one, one as two;
Is there a way I could somehow do the following?
Table ONE
id c_id type
-------------------
1 1 7
2 2 7
3 3 5
4 4 7
Table TWO
id title live
-------------------
1 row1 1
2 row2 0
3 row3 0
4 row4 1
The c_id column links the data from table ONE to table TWO. Example: in table ONE, if the c_id is 2, that row in table ONE will be directly linked to table TWO's row with id 2, which has a title of "row2".
I want to select from table ONE, everything with type 7, but only if their associated data in table TWO has live set to 1.
Here's how I thought I'd do it, but this doesn't seem to work:
SELECT * FROM ONE, TWO WHERE ONE.type='7' AND TWO.live='1' ORDER BY ONE.id DESC LIMIT 5
I would expect the above to return only rows 1 and 4 from table ONE, because although table ONE has three rows with type "7", only rows 1 and 2's associated row in table TWO have live set to 1.
You were close... try using an implicit join:
SELECT ONE.* FROM ONE, TWO WHERE ONE.type='7' AND TWO.live='1' AND ONE.c_id = TWO.id ORDER BY ONE.id DESC LIMIT 5
select * from one join two on c_id = two.id where type=7 and live = 1
order by one.id desc limit 5
I do not know how to classify this question. Vaguely, its about using calculated value in the WHERE clause of a mysql query performed using a php script.
Here's the scenario -
I've a mysql table with structure like this: table_id[int], item_id[int], item_rating[int]
Now the item_rating column can have either a "1" or a "0" value in it. The table_id column is set to auto_increment and the item_id column can have duplicate values also.
So a typical table will look like below -
table_id item_id item_rating
1 item1 1
2 item5 0
3 item1 1
4 item1 1
5 item5 1
6 item1 0
What i intend to do i for each item_id, i count the number of item_rating = 1 and item_rating = 0 and then take the difference of item_rating values to get the final rating for that item (final_item_rating = item_rating(with value=1) - item_rating(with value=0) ).
Now the issue:
I have a php script that takes values from these tables, and then displays the item details ordered on the "final_item_rating" value - something like:
select * from table_name order by final_item_rating desc
only problem is, since this final_item_rating is not a column in itself, and is actually based on run time value of the query, how do i build a query?
hope i have the question clear :)
This query may help you:
SELECT sum(item_rating) AS SumRatings
FROM table_name
WHERE item_rating=1
GROUP BY item_id
ORDER BY SumRatings;
This query would sum the ratings, and order the result with the highest rating on top:
select item_id
, sum(case when item_rating = 1 then 1 else -1 end) as rating
from YourTable
group by
item_id
order by
sum(case when item_rating = 1 then 1 else -1 end) desc
I am creating a bulletin board application. Each bulletin can be liked or disliked by users of the site.To keep track of the likes and dislikes I have created the following database table
id user_id bulletin_id like_dislike
1 1 1 1
2 1 2 0
3 3 1 1
4 2 1 0
In the like_dislike column 1 means 'Like It', 0 means 'Don't like it'
I know how to ask.
- How many times was bulletin 1 liked (2)
- How many times was bulletin 1 disliked (1)
But How do I do a query to ask those two questions at the same time? That is, how many times was bulletin 1 liked and disliked
liked disliked
2 1
I have tried the query
SELECT count(like_dislike) AS likes, count(like_dislike) AS dislikes FROM bulletins_ld
where bulletins_id = 1 AND likes = 1 AND dislikes = 0
but all I get is two twice which is not surprising.
The only solution I can think of is having a separate like and dislike column
You can do this with an aggregate query, using opposing conditions on the single like_dislike column (I am assuming below that a '1' in that column means 'liked').
SELECT bulletin_id,
SUM(CASE WHEN like_dislike = 1 THEN 1 ELSE 0 END) AS likes,
SUM(CASE WHEN like_dislike = 0 THEN 1 ELSE 0 END) AS dislikes
FROM bulletins_ld
GROUP BY bulletin_id
Update: As per the discussion in the comments below, the like/dislike column could be normalized into its own table, like so (example deliberately silly...):
CREATE TABLE how_user_feels(
feeling_id INT,
feeling_desc VARCHAR(20)
)
INSERT INTO how_user_feels(feeling_id, feeling_desc) VALUES
(0, 'Undecided'),
(1, 'Likes It'),
(2, 'Could Do Without It')
The Likes_Dislikes column in the Bulletin table is then replaced by the foreign key feeling_id, with a default to 0. Let's say that you then enter a record in this table when a user first views a bulletin, making them "Undecided" by default, and update that record when they vote on the bulletin. You could query the results like so:
SELECT bulletin_id,
SUM(CASE WHEN feelings_id = 1 THEN 1 ELSE 0 END) AS likes,
SUM(CASE WHEN feelings_id = 2 THEN 1 ELSE 0 END) AS dislikes,
SUM(CASE WHEN feelings_id = 0 THEN 1 ELSE 0 END) AS doesnt_seem_to_care
FROM bulletins_ld b
INNER JOIN how_user_feels h ON b.feeling_id = h.feeling_id
GROUP BY bulletin_id
Keep in mind, this is just one approach, and may not be useful in your case. But if you ever decided to change or expand the model by which a user expresses their feelings for a bulletin, say to a five-star rating system, you could do that without changing the database schema - just alter the records in the how_user_feels table, and the associated queries.
For the record, there is another way to obtain the same result set, whether it is faster or slower depends on the platform. This uses a scalar subquery instead of an aggregate on the outer query. The idea is, this is supposed to be easier if you think in terms of sets. Or in terms of Dimension-Facts.
First we have to straighten out your names. Let's call your "table" bulletin_like and the main bulletin table bulletin (bulletin_id is a very silly name for either of them, that is more of a column name). And just call the boolean column like (if it is 1, like is true; if it is 0, like is false; that's what boolean means). Use the singular form for names. SELECT name AS bulletin,
(SELECT COUNT(like)
FROM bulletin_like bl
WHERE bl.bulletin_id = b.bulletin_id
AND like = 1
) AS like,
(SELECT COUNT(like)
FROM bulletin_like bl
WHERE bl.bulletin_id = b.bulletin_id
AND like = 0
) AS dislike
FROM bulletin b
You asked for the Normalisation tag,. That bulletin_like "table" is not Normalised. Get rid of theIdiot column, it serves no purpose other than a redundant column and an additional index. The PK is (bulletin_id, user_id).
Unless you want users to post multiple likes and dislikes per poster per bulletin.
This query worked for me:
SELECT bulletin_id,
sum(like_dislike) AS likes,
sum((1-like_dislike)) AS dislikes
FROM bulletins_ld
GROUP BY (bulletin_id);
This assumes that likedislike = 1 means "LIKE IT" and likedislike = 0 means "DOES NOT LIKE IT".
ID LIKES DISLIKES
1 2 1
2 0 1