I have 3 tables, all with some kind of articles: articles, columns and reports. All tables have a column called date, which contains the Unix timestamp when the record was added.
Now, I want to get the 50 most recently added records of the articles, columns and reports table and list them on a webpage. Because an article and a column can have the same unique ID, it is also necessary to know which result came from which table, for linking to the complete article (www.webpage.com/article/12 or www.webpage.com/column/12 for instance).
What is the best way to achieve this?
Frankly, the best way is probably to pull the elements into different variables. Anyway, here's an alternative if you want to do it all at once:
SELECT a.date, a.title, 'ARTICLE' category
FROM articles a
WHERE date > :date
UNION ALL
SELECT date, title, 'COLUMN' category
FROM columns
WHERE date > :date
UNION ALL
SELECT date, title, 'REPORT' category
FROM reports
WHERE date > :date
Something like that, anyway. The idea is that you can include a flag referencing the source table in each sub-select statement.
Related
I've built a maintenance database for a client with multiple tables that works fine, but now they want to be able to get reports and I'm having trouble creating a select statement across 2 tables.
A user can search repair type, start/end date and location...no issue at all returning results of repair type between 2 dates (all held in the same table), but the tables for different types of repair don't store the location info, that is held against info in the vehicle info table.
So on 1 table I can query something like:
SELECT fid from cm_repair where start_date >= '$date1' AND end_date <= '$date2'
and on the other table I can have:
SELECT id from cm_fleet where location='$loc'
Is there anyway I can combine these so that I only get rows where id and fid match?
You can use an INNER JOIN:
SELECT fid
from cm_repair as t1
join cm_fleet as t2 on t1.fid = t2.id and location='$loc'
where start_date >= '$date1' AND end_date <= '$date2'
Check this link.
Inner, left, and right join's are common options for combining tables that you might be needing here.
Inner will bring in all valid rows and selected columns from BOTH tables. Essentially if the ID you are joining is present in one table, but not the other, you could end up with columns with null values.
Left and right are similar and a bit faster at processing than the Inner since less data is returned (depending on your query and statements). Essentially it'll return all valid rows and selected columns from the left and right table, BUT if the ID that you are joining on is not in the other side of the join, that row of data will not be returned, therefore no null values.
Thanks, will try all this - however we've discovered a flaw in the way the tables are setup anyway and need to edit to include a location column in the repair table, so that will make it all much easier to search as well.
We need to grab the last and newest 20 entries from different tables. However, the GROUP BY statement skips records because we are working with LEFT JOIN on tables.
All these records are linked to unique persons in another table. We store these person's id's in an array for more queries later.
We have a few tables (in which all those person id's are stored) and we want to get them sorted and grouped.
The tables are like this:
SELECT lastRecord+personID FROM t1
SELECT lastRecord+personID FROM t2
SELECT lastRecord+personID FROM t3
SELECT lastRecord+personID FROM t4
WHERE t5.Essential_Column_Name = '1'
GROUP BY personID
ORDER BY 'all the latest entries'
LIMIT 20
With that, the relevance of all the latest entries should be equal.
We do have a timestamp column as well. Perhaps that might work better.
Any input is highly appreciated!
For people looking for an answer on this; this is the right post, answer and update to this Q:
UNION mysql gives weird numbered results
With thanks to all for the ideas and providing the paths to the right solution.
want to create a facebook type newsfeed that basically lists out different events by their timestamp. These events reside in different tables. I have some code that lets me order a result set by timestamp from the different tables. My problem is I don't know the right way to combine the results from queries of different tables into one result set. I have a feeling that UNION might be the way to do it, however, UNION seems to require that the result sets have similar numbers of columns, datatypes etc. that seems a bit hard to enforce.
Some posts have suggested the right way to do this would be to crate a separate newsfeed table but that sounds cumbersome.
This is what I have so far. Newsfeed draws different events such as comments, photo posted etc.
table comments
id|comment|timestamp
photos
id|name|timestamp
$sql = "SELECT p.name,p.timestamp from `photos` p
JOIN
SELECT c.commentc.timestamp from `comments` c
ORDER GREATEST(IFNULL(p.timestamp,0), IFNULL(c.timestamp,0))"
You can use UNION and just use null in the position of non-matching columns
SELECT id, comment, null as name, timestamp FROM comments
UNION
SELECT id, null as comment, name, timestamp FROM photos;
SQLFiddle example - http://sqlfiddle.com/#!2/f9f40f/1
I'm trying to solve a MySQL problem, I have two tables:
CATEGORIES (COLUMNS: _id, _name)
POSTS (COLUMNS: _id, _category, _title, _text)
_category field in POSTS is LONGTEXT and can have multiple CATEGORIES _ID's separated only by , using implode(",") PHP function.
I try to list with PHP the 10 most popular categories, and to display in () the posts in them, but without luck.
I'm not very familar with MySQL, I only know how to use SELECT FROM WHERE ORDER LIMIT, INSERT & UPDATE so I will be very happy if someone can give me a good solution. I tried to use IN() but IN() needs the _category field of POSTS to be like this '1','2','3','4', now its 1,2,3,4 without the quotes, so if anyone know how I can transform this field into list without FIELD TYPE SET, I will be pretty happy.
You may want to change your relation model to the following:
Table CATEGORIES with columns:
_id
_name
Table POSTS with columns:
_id
_title
_text
Table POSSESS with columns:
post_id (FOREIGN KEY)
category_id (FOREIGN KEY)
A tuple in POSSESS relation (table) means the post_id is in the category_id category.
the key word for this is "many-to-many" relations, if possible refactor your scheme like Mark Baker wrote.
Using the model that Dyin suggested, you would then use something like this to list the top 10 categories by popularity (assuming that the more posts a category has, the more popular it is):
SELECT
c.*, # get all values for rows in categories
count(p.post_id) AS post_count # here we are counting the posts for each category using a field alias for the count
FROM (
categories AS c, # we are aliasing the tables also to shorten the typing a bit
possess AS p # you could also use aliases to join the same table multiple times
)
WHERE
c.id = p.category_id # link the categories and the possess tables
GROUP BY c.id # without this, the query would just count all posts, this way the result set is separated into groups by category
ORDER BY post_count DESC
LIMIT 10
Given what you said about your experience with SQL, this query might seem a bit over the top for now, but I think you could use as a starting point for learning more, as always, google is your friend. Start by researching how to link tables using foreign keys and joins.
I've used this:
SELECT *, (SELECT COUNT(*) FROM offer WHERE FIND_IN_SET(type._id, offer._type)) AS _count FROM type ORDER BY _count DESC LIMIT 0, 10
Works fine for now, its table type (columns: _id, _name) and offer (columns: .., .., _types,
I remember doing this in DB class in what feels like ages ago, but can't recall it and can't seem to search for the right words.
I am trying to essentially turn a query that produces a foreach and then runs another query based on information from the first one, into one query. More clearly, I have two tables members and entries. For our purposes members has two columns member_id, member_name, and entries has entry_id, channel_id, author_id. Author_id is an FK to member_id.
I want a count of entries by each author and do it in one SQL statement. So I need a list of the member id's first then take each member id and query the entries table for the count of entries where author_id = member_id.
Programmatically it would look something like this (not full code obvi):
$mems = select member_id from members_table;
foreach($mems as $cur_mem) {
$entry_count = select count(*) from entries_table where author_id=$cur_mem[member_id];
echo $entry_count;
}
This is for MySQL and using a CMS called ExpressionEngine, which is the cause of this headache of a solution. Having a hard time describing this issue, so I can clarify any questions.
Thanks!
Try this query:
SELECT member_id,
COUNT(author_id )
FROM members_table m
INNER JOIN entries_table
ON author_id = member_id
GROUP BY member_id