Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have a few tables in my script that I need to create a timeline from all of them. The main tables are "posts" - "likes" - "comments".
posts table has rows: PID - UID - title - time_added.
likes table has rows: LID - PID - UID - time_added.
comments table has rows: CID - PID - UID - time_added.
users table has rows: UID - username.
I'm creating a page in the users' profiles called: "Timeline". It should show the actions of the user sorted by time. UID refers to the user ID.
Data example while browsing that page:
User Commented on Post xxxx at xxx_time_added_xxx.
User Liked post xxxx at xxx_time_added_xxx.
User added Post xxxx at xxx_time_added_xxx.
Is there's a way or MySQL query that can combine all these tables and arrange them by time_added?
I thought of creating a new MySQL table: user_timeline that has rows:
TID - UID - PID - LID - CID
And after each action (Post, Like, Comment) and new row is inserted in that table according to the action and add the action ID in the corresponding field and leave the others null. Then call them combined with the related table, if possible.
you can with UNION and aliasing:
select * from ((select 1 as type,time_added from posts where ...) union (select 2 as type,time_added from likes where ...) ...) order by time_added asc
NOTE: Column selection must have the same order in regards to the column type.
Do not do:
(select 1 as type,time_added from posts where ...) union (select time_added,2 as type from likes where ...)
Or if you don`t select the same number of columns in subqueries:
SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns
Your result set will be an multi dimensional array as follows:
array(array('type'=>1,'time_added'=>'...'),array('type'=>2,'time_added'=>'...'));
By TYPE you know if it is a post or a like
Hope this helps
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have got a simple game: players earn points, what I store in the POINTS table. I'm afraid the table will be too big, so I want to summarize the points of last month because optimalizing.
For example ID 42 player has got 120 records in the table between 01.08.2019 and 31.08.2019, with 560 points. I would like to delete the 120 rows, and insert only one, with 560 points. I am using PHP(5.6.40) and MySQL.
I have no idea how to solve it. Should I make an archive table, copy the records to it from original table, delete the copied records from original table, and insert back the summarized records only?
POINTS table
id : auto inc. int
timestamp : (unsigned) int
playerid : int
points : tinyint
Do not delete the data from your tables unless there is a very good reason to do so. You want to keep all the data and aggregate it in some other way. What if you make a mistake or a bug and you would like to recalculate the scores?
Generally the SQL aggregate function SUM(score) works really well with indexes and you might have thousands of rows and sum them up on the fly with no perceivable performance reduction.
If you expect a lot of rows in your table you could create an aggregate table and keep the summed up values in it. For example add another column to your players table called total_score and every new record you add for that player in points table will be added to the running total of total_score. You could handle this in your application layer or use DB triggers to update the totals automatically.
You can create a separate table for one maintaining summary of points. Do not delete the master table as it will serve as a point of reference in future if something goes wrong.
Create new table with same structure
CREATE table points_sum LIKE points
Then do one time cleaning to summarize points
INSERT INTO points_sum VALUES (
SELECT id, timestamp, playerid, SUM(points) AS points
FROM points
GROUP BY playerid, FROM_UNIXTIME(timestamp, '%Y-%m')
)
Later all values you store should be summed up before inserting/updating into the table. If player information is not present for the current month, then INSERT else UPDATE. Insert is pretty simple. Here is how you would update it.
UPDATE points_sum
SET points = points + 50
WHERE playerid = '123'
AND timestamp >= UNIX_TIMESTAMP('2018-08-01 00:00:00')
AND timestamp <= UNIX_TIMESTAMP('2018-08-31 23:59:59')
I have two tables in my DB
1.USER TABLE
2.POST table (id,title)
3.FAVOURITE TABLE (id,post_id,user_id)
I want to get post that favourite by a particular user along with total favourites of each post.
SELECT post.title,COUNT(favourite.post_id) as total_favourites FROM post
JOIN favourite ON post.id=favourite.post_id
WHERE favourite.user_id=119 GROUP BY favourite.post_id
I got the result but there is a problem with total_favourites its always give count as 1 even if there is more than one favourite for particular post.
for eg:
favourite table
id post_id,user_id
1 1 1
1 1 2
in the above post has id 1 have two favourites but in my query i will get count as 1
An user only can mark as favourite a post one time, so the total count always be 1.
Try grouping by user_id instead.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have a table called ad_view and it has 18.9 million number of data inside that table.
This is the table design of ad_vew
ad_view
-------
ad_id
network_id
publisher_id
landingpage_id
advertiser_id
I am using this query to get the ad_id and the count of ad_id depending on the network_id, so in this case the network_id is 4.
select ad_id,count(ad_id) as strength
from ad_view
where network_id = 4
group by ad_id
order by strength desc
limit 10
This query takes forever to load. Do you have any suggestion how to make this query fast?
I am not a database expert, if it takes to redesign this table, I would do that.
Any suggestion will be greatly appreciated, thanks!
This will help:
ALTER TABLE ad_view ADD INDEX (network_id, ad_id).
Make sure you have tuned your innodb_buffer_pool_size to hold the frequently-requested portion of your table in memory.
You might like my presentation, How to Design Indexes, Really. That presentation doesn't go into indexing for GROUP BY, but you can think of it like a range condition.
1 Create an index on network_id since you're searching by it
ALTER TABLE `ad_view` ADD INDEX (`network_id`);
2 If you're trying to get the count of ad_id for a given network_id, why do you need ad_id in your results? and why do you need to order by? I don't understand this. If all you want is how many ad_ids for network_id 4, then do:
SELECT COUNT(IF(network_id=4,1,null)) as strength from ad_view
It will return just a number. See this demo
PS: your initial post included a broken query (in the order by clause), which you changed after I made a comment. Your current query still doesn't give you what you say you want. I just tried it on this fiddle
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I am building a tourism platform and I am planning to have the following users table:
USERS: id, username, password, email, first_name, last_name, description, picture_path
My goal is to have two groups of users:
tour operators
tourists
When a tour operator logs in, I want the system to recognize that he is from the group "tour operators" so that different information is going to be displayed him as if he was part of the "tourists" group.
My question: What is the best way to realize these two user groups in my database design?
You should have UserCategories table:
CREATE TABLE `UserCategories` (
UC_ID INT PRIMARY KEY AUTO_INCREMENT,
IC_Title VARCHAR(100)
)engine=innodb;
Then in your users table have a column called CategoryID and have it reference UserCategories table on UC_ID = CategoryID.
This way you will know which category user belongs to whether its operator ID 1 or tourist ID 2.
The way I would do it is I would have another table call it Permissions that references Permission to UserCategories. That way you will be able to customize what kind of access Tourists should have.
Update:
SELECT COLUMN1, COLUMN2 ...
FROM users
INNER JOIN UserCategories ON UC_ID = CategoryID
INNER JOIN Permissions ON UC_ID = PCategoryID
WHERE Permission = 'update_data' OR Permission = 'delete_data'
Or you could grab all permissions for a specific user category and see if currently logged in user has that permission to perform that action.
An easy method of doing this would be to add a column to your USERS table which store the type of the group. For example: groupType could store either operator or tourist and depending on that value, you can show or hide stuff in your page.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Well so I got a tiny problem, I got a db and 2 tables like this
Table User
user_id
Table UserrToData
user_id int pk
data_id int
Table UserData
data_id
name
nick
I got the user_id and i need to get records from the userdata , is it possible using 1 query?
Of course, if anyone know how I would really appreciate if he would help me : )
For the selecting I got only the relationship user_id > data_id
update
Guys I got huge db I just simplified the problem to the minimum ^_-
Hope this helps:
SELECT name, nick
FROM UserToData utd INNER JOIN UserData ud ON utd.data_id = ud.data_id
WHERE utd.user_id = [supplied userid]
With such little data, however, there is no need for separate tables, just store name and nick in the User table:
Table User
user_id pk
name
nick
You should overthink your database design. The highest aim is always to prevent redundancies.
If you want the user to have more than one userdata entry you should define your database like this:
Table User
user_id pk
Table UserData
data_id pk
user_id fk
name
nick
So the query would be SELECT * FROM UserData WHERE user_id = ?.
If you only want the user to have one set of userdata you should integrate it into the user table:
Table User
user_id pk
name
nick
So the query would be SELECT * FROM User WHERE user_id = ?.
Why have you put the name and nick in a separate table? You can just put the data in one user table. Might be wise to learn more about how to formulate entities and relations in your database.
Either way, if you ever need to do something like this in Zend at a later time, you can use Zend_Db_Select and do a join. Lookie lookie: http://framework.zend.com/manual/1.12/en/zend.db.select.html#zend.db.select.building.join