mysql group and remove duplicates - php

I have got this mySQL table:
id | url | origin | categroy | date
1 | url.com/1 | US | news | 2015-10-01 12:39:19
2 | url.com/1 | | | 2015-10-01 13:59:34
3 | url.com/2 | CN | news | 2015-09-01 12:45:26
4 | url.com/3 | | | 2015-08-12 09:10:10
5 | url.com/3 | US | news | 2015-09-14 04:56:36
6 | url.com/4 | US | | 2015-09-09 12:12:09
is there a way to group the entries by the url and remove the duplicates in one mySQL call without creating a new table?
desired table:
1 | url.com/1 | US | news | 2015-10-01 12:39:19
3 | url.com/2 | CN | news | 2015-09-01 12:45:26
5 | url.com/3 | US | news | 2015-09-14 04:56:36
6 | url.com/4 | US | | 2015-09-09 12:12:09
I am a beginner and I tried to solve this with a php script which failed. I guess there is a fairly easy SQL-answer to that, but I couldn't find an easy answer on Stackoverflow.
Thank you very much!

Try this query
SELECT id, url,
SUBSTRING_INDEX(GROUP_CONCAT(origin ORDER BY date DESC),',',1) as origin_value,
SUBSTRING_INDEX(GROUP_CONCAT(category ORDER BY date DESC),',',1) as category_value,
SUBSTRING_INDEX(GROUP_CONCAT(date ORDER BY date DESC),',',1) as date_value FROM tablename
GROUP BY url
ORDER BY url,date DESC

Related

Mysql convert sql to TRANSPOSE sql

I have quiet interesting task at my university.
I have DB table:
----------------------------------------
| id | fee | status | created_at |
----------------------------------------
| 1 | 10 | COMPLAINABLE | 2018-05-01 |
| 2 | 15 | COMPLAINABLE | 2018-05-01 |
| 3 | 18 | COMPLAINABLE | 2018-05-02 |
| 4 | 1 | COMPLAINABLE | 2018-05-03 |
| 5 | 2 | COMPLAINABLE | 2018-05-03 |
----------------------------------------
I wrote SQL:
SELECT created_at AS ts, SUM(fee) AS value
FROM leads_ads
WHERE status NOT IN ('COMPLAINED', 'COMPLAIN_ACCEPTED')
GROUP BY DATE_FORMAT(created_at, '%Y-%m')
ORDER BY created_at ASC;
And at first result was fine:
-------------------------
| ts | value |
-------------------------
| 2018-05-01 | 25 |
| 2018-05-02 | 18 |
| 2018-05-03 | 3 |
-------------------------
But now i have to rewrite sql to get result like this:
---------------------------------------------------------------
| ts0 |value0| ts1 | value1 | ...... | tsn | valuen |
---------------------------------------------------------------
|2018-05-01| 25 |2018-05-02| 18 | ...... | tsn | valuen |
---------------------------------------------------------------
I tried many ways to do it but can't fine a right result(tried TRANSPOSE pivot table). So I decided to ask here. maybe someone will push me to the right way.
Thanks
Look at this article (this shows how you can resolve this with dynamic SQL): http://onlybluefeet.com/2015/01/18/how-to-rotate-rows-into-columns-in-mysql/

Find the ranking for Concatenated rows in mysql

I have a table with concatenated values within both rows, I am therefore uniquely retrieve ranking for each row in the tables.
UPDATE
The other tables has been added to question
NamesTable
NID | Name |
1 | Mu |
2 | Ni |
3 | ices |
GroupTable
GID | GName |
1 | GroupA |
2 | GroupB |
3 | GroupC |
MainTable
| NID | Ages | Group |
| 1 | 84 | 1 |
| 2 | 64 | 1 |
| 3 | 78 | 1 |
| 1 | 63 | 2 |
| 2 | 25 | 2 |
| 3 | 87 | 2 |
| 1 | 43 | 3 |
| 2 | 62 | 3 |
| 3 | 37 | 3 |
Now the first Name is equated to the first age in the table, I am able to equate them using php and foreach statements, Now the problem is with the ranking of the ages per each group. I am ranking the names uniquely on each row or group.
Results which is expected
| Names | Ages | Group | Ranking |
| Mu,Ni,ices | 84,64,78 | 1 | 1,3,2 |
| Mu,Ni,ices | 63,25,87 | 2 | 2,3,1 |
| Mu,Ni,ices | 43,62,37 | 3 | 2,1,3 |
In my quest to solving this, I am using GROUP_CONCAT, and I have been able to come to this level in the below query
SELECT
GROUP_CONCAT(Names) NAMES,
GROUP_CONCAT(Ages) AGES,
GROUP_CONCAT(Group) GROUPS,
GROUP_CONCAT( FIND_IN_SET(Ages, (
SELECT
GROUP_CONCAT( Age ORDER BY Age DESC)
FROM (
SELECT
GROUP_CONCAT(Ages ORDER BY Ages DESC ) Age
FROM
`MainTable` s
GROUP by `Group`
) s
)
)) rank
FROM
`MainTable` c
GROUP by `Group`
This actually gives me the below results.
| Names | Ages | Group | Ranking |
| 1,2,3 | 84,64,78 | 1 | 7,9,8 |
| 1,2,3 | 63,25,87 | 2 | 5,6,4 |
| 1,2,3 | 43,62,37 | 3 | 2,1,3 |
The only problem is that the ranking Values increase from 1 to 9 instead of ranking each row uniquely. Its there any idea that can help me cross over and fix this? I would be grateful for your help. Thanks

Order data within group by that has 2 different columns in MySQL

I am working with a discussion board where there will be a certain topic and the user can comment or upvote another comment. Each comment can also be replied by another user and will recieve notifications.
My notification table
notification_id is the user_id of the logged in user that will receive the notification
notification_from is the user_id of the one who commented or like the users post.
notification_topic is the id of the topic plus the type of notification that will distinguish if it is a comment or an upvote
notification_comment is the comment_id in the topic
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
| notification_id | notification_pic | notification_name | notification_title | notification_user_id | notification_date | notification_from | notification_topic | notification_comment | type | status |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
| 1 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188338 | 32 | 83_upvote | 1 | upvote | read |
| 2 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188342 | 32 | 83_comment | 1 | comment | read |
| 3 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 2 | 1380188505 | 93 | 83_upvote | 1 | upvote | read |
| 4 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 2 | 1380188509 | 93 | 83_comment | 1 | comment | read |
| 5 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 0 | 1380246975 | 93 | 83_comment | 1 | comment | unread |
| 6 | 93_1379990163_thumb.jpg | vhon samson | Toyota and Nissan in vehicle recall | 2 | 1380247149 | 93 | 225_comment | 3 | comment | read |
| 7 | default.gif | kath aguilar | Chrysler files papers for share sale | 2 | 1380253584 | 7 | 83_comment | 1 | comment | read |
| 8 | default.gif | kath aguilar | Chrysler files papers for share sale | 93 | 1380253870 | 7 | 83_comment | 2 | comment | unread |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
My query
This is how I query and group my table:
SELECT *, COUNT(notification_topic) AS topic_count
FROM tbl_notification
WHERE notification_user_id = '{$_SESSION['id']}'
GROUP BY notification_topic
ORDER BY notification_date DESC
LIMIT 8
This is the result of the query:
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
| notification_id | notification_pic | notification_name | notification_title | notification_user_id | notification_date | notification_from | notification_topic | notification_comment | type | status | topic_count |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
| 6 | 93_1379990163_thumb.jpg | vhon samson | Toyota and Nissan in vehicle recall | 2 | 1380247149 | 93 | 225_comment | 3 | comment | read | 1 |
| 2 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188342 | 32 | 83_comment | 1 | comment | read | 3 |
| 1 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188338 | 32 | 83_upvote | 1 | upvote | read | 2 |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
See it on sqlfiddle.
What I need
I need to get the count so that I can come up with a notification like on facebook, like this:
My main problem is I can't ORDER it by notification_date before the GROUP BY because I need to isolate each notification_comment by its notification_topic. I want the latest user that commented or like each topic to be displayed. How will I do this?
If I've understood your problem correctly then you want the groupwise maximum, which can be obtained by selecting the identifying criteria in the group and then joining back to your table:
SELECT *
FROM tbl_notification NATURAL JOIN (
SELECT notification_topic,
notification_user_id,
MAX(notification_date) AS notification_date,
COUNT(*) AS topic_count
FROM tbl_notification
WHERE notification_user_id = 2
GROUP BY notification_topic,
notification_user_id
) AS t
ORDER BY notification_date DESC
LIMIT 8
See it on sqlfiddle.

Display 2 filtered columns from 2 tables in PHP

I have 2 tables - users and users_audit, need to display results from 2 separate queries into 2 columns with relation to each other. I already figured out both queries.
query for users: SELECT rowid,data FROM users WHERE columnid = 1 GROUP BY rowid;
+-------+------------+
| rowid | data |
+-------+------------+
| 1 | John |
| 2 | Abi |
| 3 | Tony |
| 4 | Gregg |
| 5 | Jon |
| 6 | Victor |
| 7 | Daniel |
query for users_audit: SELECT date_created FROM users_audit WHERE rowid = 6 ORDER BY date_created DESC, date_created DESC LIMIT 1;
Purpose of the query is to display latest date_created for particular rowid.
+---------------------+
| date_created |
+---------------------+
| 2012-07-04 09:20:12 |
+---------------------+
Table users_audit looks like this:
SELECT * FROM users_audit;
+-------+---------+--------------+-------------+---------------------+
| id | rowid | before_value | after_value | date_created |
+-------+---------+--------------+-------------+---------------------+
| 1 | 6 | 3 | 5 | 2012-06-29 15:48:11 |
| 2 | 5 | Out (0) | 2 | 2012-07-04 09:20:10 |
| 3 | 6 | 5 | 4 | 2012-07-04 09:20:12 |
| 4 | 7 | 3 | 6 | 2012-07-04 09:20:14 |
| 5 | 3 | 2 | 3 | 2012-07-04 09:20:16 |
| 6 | 15 | 6 | 5 | 2012-07-04 09:20:22 |
I need to display 2 columns - data from users and date_created from users_audit for each rowid. It means query for users_audit must be run for each rowid (in the loop?).
Expected result displayed in php is:
+------------+----------------------+
| data | date_created |
+------------+----------------------+
| John | (latest date) |
| Abi | (latest date) |
| Tony | (latest date) |
| Gregg | (latest date) |
| Jon | (latest date) |
| Victor | 2012-07-04 09:20:12 |
| Daniel | (latest date) |
How can this be achieved this in php?
Why cant you just create a view and use a join to create the table you want?
SELECT users.data, users_audit.date_created FROM users
INNER JOIN users_audit ON users.rowid = users_audit.rowid
Or am I missing something here?
EDIT
SELECT users.data, users_audit.date_created FROM users
INNER JOIN users_audit ON users.rowid = users_audit.rowid
WHERE users_audit.date_created = (SELECT MAX(date_created) from users_audit
GROUP BY rowid)
I believe this should work..? Let me know.

MYSQL Query locking up server

When trying to execute this query my mysql server cpu usage goes to 100% and the page just stalls. I setup an index on (Client_Code, Date_Time, Time_Stamp, Activity_Code, Employee_Name, ID_Transaction) it doesn't seem to help. What steps can I go about next to fix this issue? Also there is already one index on the database if that matters any. Thanks
Here is what this query does
Database info
ID_Transaction | Client_Code | Employee_Name | Date_Time |Time_Stamp| Activity_Code
1 | 00001 | Eric | 11/15/10| 7:30AM | 00023
2 | 00001 | Jerry | 11/15/10| 8:30AM | 00033
3 | 00002 | Amy | 11/15/10| 9:45AM | 00034
4 | 00003 | Jim | 11/15/10| 10:30AM | 00063
5 | 00003 | Ryan | 11/15/10 | 12:00PM | 00063
6 | 00003 | bill | 11/14/10 | 1:00pm | 00054
7 | 00004 | Jim | 11/15/10 | 1:00pm | 00045
8 | 00005 | Jim | 11/15/10| 10:00 AM| 00045
The query takes the info above and counts it like so. By the most recent entry for each client_code. In this case the query would look like this. After php.
Jerry = 1
2 | 00001 | Jerry | 11/15/10| 8:30AM | 00033
Amy = 1
3 | 00002 | Amy | 11/15/10| 9:45AM | 00034
Ryan = 1
5 | 00003 | Ryan | 11/15/10 | 12:00PM | 00063
Jim = 2
7 | 00004 | Jim | 11/15/10 | 1:00pm | 00045
8 | 00005 | Jim | 11/15/10| 10:00 AM| 00045
$sql = "SELECT m.Employee_Name, count(m.ID_Transaction)
FROM ( SELECT DISTINCT Client_Code FROM Transaction)
md JOIN Transaction m ON
m.ID_Transaction = ( SELECT
ID_Transaction FROM Transaction mi
WHERE mi.Client_Code = md.Client_Code AND Date_Time=CURdate() AND Time_Stamp!='' AND
Activity_Code!='000001'
ORDER BY m.Employee_Name DESC, mi.Client_Code DESC, mi.Date_Time DESC,
mi.ID_Transaction DESC LIMIT 1 )
group by m.Employee_Name";
Is there a better way to write this query so it doesnt bog down my system? The query works fine with 10 database entries but it locks my server up when the database has 300,000 entries.
Thanks
Eric
+----+--------------------+-------------+--------+------------------------+--------------+---------+----------------+------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------------+--------+------------------------+--------------+---------+----------------+------+----------+----------------------------------------------+
| 1 | PRIMARY | <derived2> | ALL | [NULL] | [NULL] | [NULL] | [NULL] | 8 | 100.00 | Using temporary; Using filesort |
| 1 | PRIMARY | m | index | [NULL] | search index | 924 | [NULL] | 21 | 100.00 | Using where; Using index; Using join buffer |
| 3 | DEPENDENT SUBQUERY | mi | ref | search index,secondary | search index | 18 | md.Client_Code | 3 | 100.00 | Using where; Using temporary; Using filesort |
| 2 | DERIVED | Transaction | index | [NULL] | secondary | 918 | [NULL] | 21 | 38.10 | Using index |
+----+--------------------+-------------+--------+------------------------+--------------+---------+----------------+------+----------+----------------------------------------------+
What about going with multiple GROUP BY's instead of the all the sub queries to simplify things.... something like:
SELECT * FROM Transaction WHERE Date_Time=CURdate() AND Time_Stamp!='' AND Activity_Code != '000001' GROUP BY Client_Code, Employee_Name
If I'm understanding your query correctly then something like this would solve the issues and prevent the need for sub queries.
You'll definitely want to do a join instead of a sub select.
Also, how many records are you viewing? Is pagination and using limit out of the question?
If you set up your initial query modified with inner/outer joins as a view and it doesn't crash, you'll be one step closer. Once the view is set up, you'll be able to use a much less complicated select statement - potentially paginated.

Categories