I have two tables:
access(name, id, check, key)
events(name, key, event_name)
I am trying to print some things from these tables into a php/html table with these columns:
name, key, event_name, access count
My trouble being I would like each event to display the "count" of access rows that have the same key.
Event table example:
name key event_name
test 1 first
joe 2 second
And the access table...
name id check key
test 123 yes 1
test 1235 yes 1
joe 175 yes 2
joe 852 yes 2
test 5843 yes 1
test 123455 yes 1
The resulting table I am hoping to look like this:
name key event_name access count
test 1 first 4
joe 2 second 2
Does anybody know how to do this? I've gotten to this but it obviously doesn't work because the key isn't given to the inner select query...
select event_name, name, key,
(SELECT COUNT(key) FROM access WHERE key=key AND name=name)
from event;
Thank you to anyone who takes a look and might have any ideas! I've been staring at this and w3schools for hours
At present your subquery will return a count of all rows as it is not correlated to the main query, so both occurrences of key in key=key will refer to the same column and the expression will always be true (likewise for name). To correlate the subquery, add table references:
select event_name, name, key,
(SELECT COUNT(key) FROM access a WHERE a.key=e.key AND a.name=e.name) AS `access count`
from event e
You can also get the same results with a join and aggregattion:
select e.name, e.key, e.event_name, count(*) access_count
from event e
left join access a on a.key = e.key and a.name = e.name
group by e.name, e.key, e.event_name
Related
I have a complicated select like:
select id from table
left join...
left join... (a lot of joins)
where ... (a lot of ANDs and ORs)
order by... (a lot of orders)
and I'm getting a result like:
1234
5565
7212
2212
etc.
I have an id which belongs to the result-set, like 7212, and want to know which row in the result-set matches the id (starting with row 0 this would be row 2 in my example).
Right now I'm reading all data and compare it in php, but I was wondering if there is a SQL-statement which does that for me and results 2 when entering 7212.
In fact I want to get the previous and next ids (row 1 and row 3 = 5565 and 2212), if thats somehow possible in 1 query that would be even better.
You can select the number row:
select #rownum:=#rownum+1 No, foo, bar from table, (SELECT #rownum:=0) r;
It's a possible duplicate of the question asked here: How to show sequential number in MySQL query result
Add an auto_increment index for each selected rows:
SELECT
#i:=#i+1 as index,
id
FROM table, (SELECT #i:= 0) AS i
LEFT JOIN...
LEFT JOIN...(a lot of joins)
WHERE ... (a lot of ANDs and ORs)
ORDER BY... (a lot of orders)
Give you this:
index id
1 1234
2 5565
3 7212
4 2212
How would I write a query that would select the name of a person (a column in the row) given that they have enough rows to meet all conditions?
For example, I have a database set up like so:
name permission_id
Bob 1
Bob 2
Jerry 3
Jerry 1
Jose 2
Billy 1
Billy 2
How would I only select the people that have permission id 1 and 2? In other words, I would like a query that checks every person by name to see if they have all the permissions requested.
In this example if I was to check for all users to who have permission 1 and 2 I should get Bob and Billy as a return value.
Here is my current query:
$this->db->select('center_user_permissions.id, center_users.first_name, center_users.last_name');
$this->db->from('center_user_permissions');
$this->db->where_in('permission_id', $permission_ids);
$this->db->join('center_users', 'center_users.center_id = center_user_permissions.center_id');
Currently this query returns anybody who has either permission id 1 or 2. I need it to be 1 AND 2. But I know I can't simply make two wheres because one particular row can't have both permission ids, but the query must check all rows for the specified ids.
I believe I would need a SELECT statement inside of my where? Can anybody tell me if I'm thinking correctly? Thanks.
You can use a in clause an an having for check that the user has both the permission
select name
from center_user_permissions
where permissions_id in (1,2)
group by name
having count(*) = 2
I'm not sure how to build this query in CodeIgniter, but you could INNER JOIN for each permission ID you want the user to have:
SELECT center_users.center_id, center_users.first_name, center_users.last_name
FROM center_users
INNER JOIN center_user_permissions AS p1 ON p1.center_id=center_users.center_id AND p1.permission_id=1
INNER JOIN center_user_permissions AS p2 ON p2.center_id=center_users.center_id AND p2.permission_id=2
You could check for more permissions by adding a INNER JOIN for each additional permission you wanted to require.
MySQL's GROUP BY and HAVING
Not user what kind of DB interface you're using in $this->db, but it may make things a little tricky. If I start with a raw SQL query:
SELECT
center_user_permissions.id,
center_users.first_name,
center_users.last_name
FROM center_user_permissions
LEFT JOIN center_users
ON center_users.center_id = center_user_permissions.center_id
WHERE center_user_permissions.permission_id in (1,2)
Group by name, where count of permission_id is > 1
This will group rows by first_name (so you'll only get one row for each unique name). Doing do allows you to run aggregate functions (SUM(), MAX(), COUNT()) against the rows that were "grouped" into a single row.
SELECT
center_user_permissions.id,
center_users.first_name,
center_users.last_name
FROM center_user_permissions
LEFT JOIN center_users
ON center_users.center_id = center_user_permissions.center_id
GROUP BY center_users.first_name
WHERE center_user_permissions.permission_id in (1,2)
HAVING COUNT(center_user_permissions.permission_id)>1
select distinct(name),.. as name from 'center_user_permissions',center_users where
center_users.center_id = center_user_permissions.center_id and permissions_id in (1,2)
substitute .. with your other fields and put in distinct the value that you want to be unique
I am using mysql database.
I have two table one is user_songs and second is user_like
Fields of user_song:
id(auto incement)
song_id
user_id
song_name
song_file
Fields of user_like:
id(auto incement)
song_id
uder_id
like
In user_like I am saving data where any user going like song so each row contain data like:
1 1 1 1
Please note like saves either 0 or 1.0 for dislike and 1 for like.
Now I need to find out top 20 most like songs id from user_like and get all data from user_songs from user_songs.
How to do this?
Thanks in advance to spend your valuable time to solve this query.
SELECT a.*, b.totalLike
FROM user_song a
INNER JOIN
(
SELECT song_id, COUNT(*) totalLike
FROM user_like
GROUP song_id
) b ON a.song_id = b.song_ID
ORDER BY totalLike DESC
LIMIT 20
Caution: the query above doesn't handle tie up values on totaluserLike result. It will only display 20 records on the result list.
Here is a simplified look at the problem I am trying to cleanly solve via a MySQL query. This is not the actual table I am dealing with.
If I have the following table:
Name Buyer ID
John Fred 4
John Smith 3
Fred Sally 2
John Kelly 1
I would like a query to return the following:
Name Buyer ID
John Fred 4
Fred Sally 2
Such that we group by 'name' and show the latest row / buyer / ID.
I tried to implement this by performing a nested select statement, wherein I first performed "ORDER BY ID DESC" then, on the outermost SELECT, "GROUP BY NAME". And, while this is a roundabout way of solving the problem, it seemed that, by virtue of the ordering, the correct selection would be returned to me. Unfortunately, "GROUP BY" does not 'guarantee' that the 'Buyer' column will contain the expected entry.
Any helpful suggests for implementing this as a query? At the moment, I have a highly-inefficient PHP 'version' of the query running on a large table dump - definitely not the best choice.
Try this one, the idea behind the subquery is that it gets the latest ID for each Name using MAX (aggregate function). Then join it against the table itself on the two columns of the subquery.
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT name, MAX(ID) maxID
FROM tableName
GROUP BY name
) b ON a.Name = b.Name AND
a.ID = b.MaxID
SQLFiddle Demo
Another alternative is to load the data sorted in a subquery, then group on the results. I can't cite this, but I've read in a few places there's no (discernable) performance hit on this.
So something like:
SELECT *
FROM (
SELECT *
FROM `yourtable`
ORDER BY `id` DESC
) as `tmp`
GROUP BY `name`
I have 2 tables
Table name Dist.
NAME|Phone|ID
----------------
Oakley|555-555|1
Maui|666-666|2
lux|777-7777|3
Table name Patientacct.
Name|prescription|id|orderfrom
-------------------------------
bob|20-20|1|oakley
billy|15-20|2|Oakley, Maui
kim|20-20|3|Lux
I'm looking for a display like
Oakley
--------------------
Bob
Billy
Maui
------------------
Billy
Lux
--------------
kim
Trials so far
SELECT *
FROM `dist`
JOIN `patientacct` ON patientacct.dist LIKE CONCAT('%', `dist`.name ,'%')
GROUP BY `dist`.name
This showed only 1 dist
If I drop the group by example:
SELECT *
FROM `dist`
JOIN `patientacct` ON patientacct.dist LIKE CONCAT('%', `dist`.name ,'%')
I get the record twice so what I need is somewhere between the two. I'm extremely new to joins so be easy when explaining.
you must change your tables structure and you need to add a relation table with this values:
orders:
dist_id, patientacct_id PRIMARY_KEY(dist_id, patientacct_id)
First of all, please make the table structure relational. Have a primary auto_increment value in each table and use the primary key from the Dlist foreign key to Patientacct. This way, a simple join would fetch the record you have wanted.
Regarding the display, what do you mean you don't want record twice. Since you are using join, you will get two records for Oakley with the patient Bob and Billy. That's what you wanted and it would be like that by a simple join too in a relational table.