MySQL aggregation by strings - mysql

I have an activities table like below (also contains some other columns):
+------------------+---------------+------------+
| data | event | logged_on |
+------------------+---------------+------------+
| 12345 | File | 2015-04-08 |
| 25232 | Bulletin | 2015-04-08 |
| 7890 | File | 2015-04-08 |
| youtube | Search | 2015-04-07 |
| 13568 | Bulletin | 2015-04-07 |
| 25232 | Bulletin | 2015-04-07 |
| 7890 | File | 2015-04-07 |
+------------------+---------------+------------+
I want to fetch unique data values for latest date. So the required result would be:
+------------------+---------------+------------+
| data | event | logged_on |
+------------------+---------------+------------+
| 12345 | File | 2015-04-08 |
| 25232 | Bulletin | 2015-04-08 |
| 7890 | File | 2015-04-08 |
| youtube | Search | 2015-04-07 |
| 13568 | Bulletin | 2015-04-07 |
+------------------+---------------+------------+
But a select distinct on all the three columns above returns the same value of data for different dates. I cannot remove logged_on from the select query as it's required elsewhere.
In MySQL, i tried using the following query:
SELECT DISTINCT
data,
event,
MAX(logged_on) AS latest_log_date
FROM
activites
WHERE
username = %%(username)s
GROUP BY
data
ORDER BY id DESC, latest_log_date DESC
LIMIT %%(limit)s
;
But this does not seem to work. I'm getting the some result, which looks like it's correct, but it isn't. And i'm not able to reason about it. Any ideas?

Use NOT EXISTS to return only rows that has no later with same data/event.
SELECT data, event, logged_on AS latest_log_date
from activites a1
where not exists (select 1 from activites a2
where a1.data = a2.data
and a1.event = a2.event
and a2.logged_on > a1.logged_on)
I'm not quite sure if this is what you want. Perhaps you need to remove and a1.event = a2.event from the sub-query.

SELECT data, event, logged_on
FROM activities A1
WHERE logged_on = (SELECT A2.logged_on FROM activities A2
WHERE A2.data = A1.data AND A2.event = A1.event
ORDER BY A2.logged_on DESC LIMIT 1);

Maybe i have not got your question clear, but this query is giving me your required output
select data,event,logged_on from activities group by data order by logged_on desc;

Related

Select value from table sorted by a certain order from another table

I want to select value from table sorted by a certain order.
I have a table called test that looks like this:
| date | code | value |
+----------+-----------+----------+
| 20050104 | 000005.SZ | -6359.19 |
| 20050104 | 600601.SH | -7876.34 |
| 20050104 | 600602.SH | -25693.3 |
| 20050104 | 600651.SH | NULL |
| 20050104 | 600652.SH | -15309.9 |
...
| 20050105 | 000005.SZ | -4276.28 |
| 20050105 | 600601.SH | -3214.56 |
...
| 20170405 | 000005.SZ | 23978.13 |
| 20170405 | 600601.SH | 32212.54 |
Right now I want to select only one date, say date = 20050104, and then sort the data by a certain order (the order that each stock was listed in the stock market).
I have another table called stock_code which stores the correct order:
+---------+-----------+
| code_id | code |
+---------+-----------+
| 1 | 000002.SZ |
| 2 | 000004.SZ |
| 3 | 600656.SH |
| 4 | 600651.SH |
| 5 | 600652.SH |
| 6 | 600653.SH |
| 7 | 600654.SH |
| 8 | 600602.SH |
| 9 | 600601.SH |
| 10 | 000005.SZ |
...
I want to sorted the selected data by stock_code(code_id), but I don't want to use join because it takes too much time. Any thoughts?
I tried to use field but it gives me an error, please tell me how to correct it or give me an even better idea.
select * from test
where date = 20050104 and code in (select code from stock_code order by code)
order by field(code, (select code from stock_code order by code));
Error Code: 1242. Subquery returns more than 1 row
You told us that you don't want to join because it takes too much time, but the following join query is probably the best option here:
SELECT t.*
FROM test t
INNER JOIN stock_code sc
ON t.code = sc.code
WHERE t.date = '20050104'
ORDER BY sc.code_id
If this really runs slowly, then you should check to make sure you have indices setup on the appropriate columns. In this case, indices on the code columns from both tables as well as an index on test.date should be very helpful.
ALTER TABLE test ADD INDEX code_idx (code)
ALTER TABLE test ADD INDEX date_idx (date)
ALTER TABLE code ADD INDEX code_idx (code)

How to display the current recent rows according to time?

The following database generated by (select * from users).How can i display the recent rows according to time(i.e for time i had used date +%s).But here it displays all timing .I nee dthe rows with the recent update time.
| time | userid | groupid |
+------------+----------+-----------+
| 1477044791 | spolishe | MEMS |
| 1477044791 | ssarkar | HCG |
| 1477044791 | svaranas | PDSP_DES |
| 1476868065 | dnehra | HCG |
| 1476868065 | dprabhu | PDSP_DES |
My expected Output:(but it sould be generated by using some linux commands like date +%s).Is there any linux commands which fetches the only the last recent time rows (or) Is it possible to use inside insert mysql query by storing in some variable name.
| time | userid | groupid |
| 1477044791 | spolishe | MEMS |
| 1477044791 | ssarkar | HCG |
| 1477044791 | svaranas | PDSP_DES |
Do you want to represent the time in proper date formant? if so;
select from_unixtime(time), * from user order by time desc
You could specify that you only want items where the time is equal to that of the largest value that column holds in the table.
SELECT * FROM users where time = (Select max(time) from users);

Retrieve all not logged in users from mysql tables (SQL query)

I have 2 tables listed below:
+-------------+-----------+--------------+-------------------------------+
| v3_customer |
+-------------+-----------+--------------+-------------------------------+
| customer_id | firstname | lastname | email |
+-------------+-----------+--------------+-------------------------------+
| 1 | Piet | Pizza | piet.pizza#example.com |
| 2 | Klaas | Hein | klaas.hein#example.com |
| 3 | Henk | Crowdcontrol | henk.crowdcontrol#example.com |
+-------------+-----------+--------------+-------------------------------+
+-------------+-------------+---------------+
| v3_customer_activity |
+-------------+-------------+---------------+
| activity_id | customer_id | key |
+-------------+-------------+---------------+
| 1 | 1 | login |
| 2 | 1 | order_account |
| 3 | 2 | login |
+-------------+-------------+---------------+
What i want is to select all customers which haven't logged in yet (note the login key in v3_customer_activity). So in this case that would be the customer with customer_id: 3
I'm using a mysql database.
I have tried using the following query:
SELECT DISTINCT v3_customer.customer_id, v3_customer.firstname, v3_customer.lastname, v3_customer.email FROM `v3_customer` JOIN v3_customer_activity ON v3_customer.customer_id = v3_customer_activity.customer_id WHERE v3_customer.customer_id != (SELECT v3_customer_activity.customer_id FROM v3_customer_activity)
In the hope it would iterate between the rows found in the subquery.
This resulted in an error telling me a subquery may not contain multiple rows.
TL;DR
What I want is to retrieve every customer from v3_customer who is not listed in the table v3_customer_activity
Try this:
select v3_customer.* from v3_customer
left join v3_customer_activity on v3_customer.customer_id=v3_customer_activity.customer_id
where v3_customer_activity.customer_id is null;
Left join v3_customer table with v3_customer_activity and filter records which are not matched.
select v3_customer.* from v3_customer
where v3_customer.customer_id not in (SELECT v3_customer_activity.customer_id FROM v3_customer_activity)

merger one row with null values to not null values of another row mysql

I want to merge two rows into one.The below format is in the database.
+----+---------+-----------------------+-------------------------+
| id | appid | photo | signature |
+====+=========+=======================+=========================+
| 1 | 10001 | 10001.photograph.jpg | NULL |
| 2 | 10001 | NULL | 10001.signature.jpg |
+----+---------+-----------------------+-------------------------+
I want a mysql query so that i can fetch data like below,
+--------+------------------------+-------------------------+
| appid | photo | signature |
+========+========================+=========================+
|10001 | 10001.photograph.jpg | 10001.signature.jpg |
+--------+------------------------+-------------------------+
Kindly suggest...
You can also use max function
select appid,
max(photo) photo,
max(signature) signature
from test
group by appid
Demo
This should do this:
select t1.appid,t1.photo,t2.signature from mytable t1 join mytable t2 on t1.appid=t2.appid where t1.id=1 and t2.id=2

MySQL using GROUP BY to group by multiple columns

I'd like to use GROUP BY multiple columns, I think it's best to start with an example:
SELECT
eventsviews.eventId,
showsActive.showId,
showsActive.venueId,
COUNT(*) AS count
FROM eventsviews
INNER JOIN events ON events.eventId = eventsviews.eventId
INNER JOIN showsActive ON showsActive.eventId = eventsviews.eventId
WHERE events.status = 1
GROUP BY showsActive.venueId, showsActive.showId, showsActive.eventId
ORDER BY count DESC
LIMIT 100;
Output:
| *eventId* | *showId* | *venueId* | *count* |
+-----------+----------+-----------+---------+
[...snip...]
| 95 | 92099 | 9770 | 32 |
| 95 | 105472 | 10702 | 32 |
| 3804 | 41225 | 8165 | 17 |
| 3804 | 41226 | 8165 | 17 |
| 923 | 2866 | 5451 | 14 |
| 923 | 20184 | 5930 | 14 |
[...snip...]
What I would like instead:
| *eventId* | *showId* | *venueId* | *count* |
+-----------+----------+-----------+---------+
| 95 | 92099 | 9770 | 32 |
| 3804 | 41226 | 8165 | 17 |
| 923 | 20184 | 5930 | 14 |
So, I want my data grouped by eventId, but only once for each showId and venueId ...
I actually have a SQL query that does that, but it has 8 subqueries and is as slow as a T-Ford ... And since this is executed on every page load, speeding things up looks like a good idea!
There are a few questions like this, and I've tried many different things, but I've been at this query for an hour and I can't seem to get it to work as I want :-(
Thanks!
You probably want either a min or a max on showid, and then not include it in the group by, I can't tell which because looking at your "prefered" resultset, you have both.
If you want your data grouped by eventId, group just by eventId and you'll get exactly the result you're looking for.
This is a MySQL feature (?) that it allows you to select non-aggregate columns, in which case it will return the first row available. In other DBMS it's achieved by DISTINCT ON, which is not available in MySQL.