Select rows with greatest value - sql

I have a MS Access query called qryA380 that uses multiple INNER JOIN to join a couple of tables.
Running the query will show the results like this:
+----+-----------+----------+------------+
| ID | Aircraft | Route.ID | Passengers |
+----+-----------+----------+------------+
| 23 | A-380 | 1 | 556 |
| 2 | A-380 | 2 | 652 |
| 54 | A-380 | 2 | 489 |
| 16 | A-380 | 1 | 598 |
| 39 | A-380 | 1 | 627 |
| 45 | A-380 | 3 | 392 |
| 74 | A-380 | 3 | 726 |
+----+-----------+----------+------------+
My plan is to select the smallest Route.ID (in this case it's 1) and the final result should be:
+----+-----------+----------+------------+
| ID | Aircraft | MinRoute | Passengers |
+----+-----------+----------+------------+
| 23 | A-380 | 1 | 556 |
| 16 | A-380 | 1 | 598 |
| 39 | A-380 | 1 | 627 |
+----+-----------+----------+------------+
I thought this would be straight forward and simple. To save some time, I create a second query to do this work:
SELECT [qryA380].ID, [qryA380].Aircraft, MIN([qryA380].Route.ID) AS MinRoute, [qryA380].Passengers
FROM [qryA380]
GROUP BY [qryA380].ID, [qryA380].Aircraft, [qryA380].Passengers
But I kept getting a table identical with the table generated by qryA380. It has all the Route.ID on the results.

The Passenger and ID column should be excluded since they have unique values. By using a Subquery, I'm now able to generate the desired results:
SELECT [qryA380].*
FROM (
SELECT MIN([qryA380].Route.ID) AS MinRoute
FROM [qryA380]
) tblMinRoute
INNER JOIN [qryA380]
ON [qryA380].Route.ID = tblMinRoute.MinRoute

Try this
SELECT [qryA380].*
FROM [qryA380]
WHERE [qryA380].Route.ID = (
SELECT min(Route.ID)
FROM [qryA380]
)

Related

In database my query getting first row When i grouped

SELECT
EVENT_ID, COUNT(*), SEQUENCE_NBR
FROM
ALERTS
WHERE
ACKNOWLEDGED = 0
AND SRC_EXT = '7878'
GROUP BY
EVENT_ID
ORDER BY
COUNT(*) DESC;
Running this query to get id,count and sequence number. by group by event id and count i am getting sequence number first row .
+----------+--------------+
| EVENT_ID | SEQUENCE_NBR |
+----------+--------------+
| 150 | 9752 |
| 150 | 9764 |
| 150 | 9775 |
| 170 | 9755 |
| 170 | 9763 |
| 170 | 9774 |
| 217 | 9748 |
| 217 | 9759 |
| 217 | 9770 |
| 218 | 9751 |
| 218 | 9762 |
| 218 | 9773 |
| 273 | 9749 |
| 273 | 9760 |
| 273 | 9771 |
| 285 | 9750 |
| 285 | 9761 |
| 285 | 9772 |
+----------+--------------+
This is my data in db by using above query
+----------+----------+--------------+
| EVENT_ID | COUNT(*) | SEQUENCE_NBR |
+----------+----------+--------------+
| 150 | 3 | 9752 |
| 170 | 3 | 9755 |
| 217 | 3 | 9748 |
| 218 | 3 | 9751 |
| 273 | 3 | 9749 |
| 285 | 3 | 9750 |
+----------+----------+--------------+
i need data in same format with seuence number should
150 | 3 | 9775
Your query is malformed. You have SEQUENCE_NBR in the SELECT, but it is not in the GROUP BY. In most databases (including the more recent versions of MySQL), this generates an error. Happily that is so.
If you want the maximum SEQUENCE_NBR, then use the MAX() function:
SELECT EVENT_ID, COUNT(*), MAX(SEQUENCE_NBR) as SEQUENCE_NBR
FROM ALERTS
WHERE ACKNOWLEDGED = 0 AND
SRC_EXT = '7878'
GROUP BY EVENT_ID
ORDER BY COUNT(*) DESC;
you can try like below
SELECT
EVENT_ID, COUNT(*), SEQUENCE_NBR
FROM
ALERTS
WHERE
ACKNOWLEDGED = 0
AND SRC_EXT = '7878'
GROUP BY
EVENT_ID
ORDER BY
COUNT(*) DESC,SEQUENCE_NBR desc;

DB2 SQL - Limit the number of groups returned

I am trying to find a way to limit the first n groups returned. I have a scenario where I want to only select 10 groups of user data and no more. How would I limit 10 groups of user data where the group size for the user can vary. Some groups may have more than 4 records for a user, some may have less than 4 records for a user. But I only want to get 10 users at a time. I tried thinking about how ROW_NUMBER() and PARTITION BY could be leveraged or even FETCH FIRST N ROWS ONLY could be leveraged, but couldn't come up with a solution.
Below is some sample data. NOTE: The GROUP_NUMBER column doesn't exist in the data set I am working with. It is what I was thinking about creating via SQL so that I can leverage this to select where the "GROUP_NUMBER" < 11 for example. I am absolutely open to other solutions given my question, but this was one solution I was thinking about but didn't know how to do it.
+-----------+--------------+-----------+-----------+----------+------------------+--------------+
| REQUESTID | USERID | COMPANYID | FIRSTNAME | LASTNAME | EMAIL | GROUP_NUMBER |
+-----------+--------------+-----------+-----------+----------+------------------+--------------+
| 157 | test.bulkup1 | 44 | BulkUp | Test | bulkup1#test.com | 1 |
| 157 | test.bulkup1 | 44 | BulkUp | Test | bulkup1#test.com | 1 |
| 157 | test.bulkup1 | 44 | BulkUp | Test | bulkup1#test.com | 1 |
| 162 | test.bulkup2 | 44 | BulkUp | Test | bulkup2#test.com | 2 |
| 162 | test.bulkup2 | 44 | BulkUp | Test | bulkup2#test.com | 2 |
| 162 | test.bulkup2 | 44 | BulkUp | Test | bulkup2#test.com | 2 |
| 162 | test.bulkup2 | 44 | BulkUp | Test | bulkup2#test.com | 2 |
| 187 | test.bulkup3 | 44 | BulkUp | Test | bulkup3#test.com | 3 |
| 187 | test.bulkup3 | 44 | BulkUp | Test | bulkup3#test.com | 3 |
| 187 | test.bulkup3 | 44 | BulkUp | Test | bulkup3#test.com | 3 |
| 187 | test.bulkup3 | 44 | BulkUp | Test | bulkup3#test.com | 3 |
| 192 | test.bulkup4 | 44 | BulkUp | Test | bulkup4#test.com | 4 |
+-----------+--------------+-----------+-----------+----------+------------------+--------------+
You can use dense_rank(). I think you want:
select t.*
from (select t.*,
dense_rank() over (order by requestId) as seqnum
from t
) t
where seqnum <= 3;

equating an entry to an aggregated version of itself

I am trying to find if an entry's value is the max of the grouped value. Its purpose is to sit in a larger if logic.
Which I'd expect would look something like this:
SELECT
t.id as t_id,
sum(if(t.value = max(t.value), 1, 0)) AS is_max_value
FROM dataset.table AS t
GROUP BY t_id
The response is:
Error: Expression 't.value' is not present in the GROUP BY list
How should my code look to do this?
You first need to compile in a subquery the max value, then join again the value to the table.
Using the public data set available here is an example:
SELECT
t.word,
t.word_count,
t.corpus_date
FROM
[publicdata:samples.shakespeare] t
JOIN (
SELECT
corpus_date,
MAX(word_count) word_count,
FROM
[publicdata:samples.shakespeare]
GROUP BY
1 ) d
ON
d.corpus_date=t.corpus_date
AND t.word_count=d.word_count
LIMIT
25
Results:
+-----+--------+--------------+---------------+---+
| Row | t_word | t_word_count | t_corpus_date | |
+-----+--------+--------------+---------------+---+
| 1 | the | 762 | 1597 | |
| 2 | the | 894 | 1598 | |
| 3 | the | 841 | 1590 | |
| 4 | the | 680 | 1606 | |
| 5 | the | 942 | 1607 | |
| 6 | the | 779 | 1609 | |
| 7 | the | 995 | 1600 | |
| 8 | the | 937 | 1599 | |
| 9 | the | 738 | 1612 | |
| 10 | the | 612 | 1595 | |
| 11 | the | 848 | 1592 | |
| 12 | the | 753 | 1594 | |
| 13 | the | 740 | 1596 | |
| 14 | I | 828 | 1603 | |
| 15 | the | 525 | 1608 | |
| 16 | the | 363 | 0 | |
| 17 | I | 629 | 1593 | |
| 18 | I | 447 | 1611 | |
| 19 | the | 715 | 1602 | |
| 20 | the | 717 | 1610 | |
+-----+--------+--------------+---------------+---+
You can see that retains the word that have the maximum word_count in the partition defined by corpus_date
Use window function to "spread" the max value over all relevant records.
this way you can avoid the Join.
SELECT
*
FROM (
SELECT
corpus,
corpus_date,
word,
word_count,
MAX(word_count) OVER (PARTITION BY corpus) AS Max_Word_Count
FROM
[publicdata:samples.shakespeare] )
WHERE
word_count=Max_Word_Count
select
id,
value,
integer(value = max_value) as is_max_value
from (
select id, value, max(value) over(partition by id) as max_value
from dataset.table
)
Explanation:
Inner select - for each row/record calculates max of value among all rows with the same id
Outer select - for each row/record compares row's value with max value for respective group and then converts true or false into respectively 1 or 0 (as per expectation in question)

MS Access SQL query from 3 tables

I have 3 tables shown below in MS Access 2010:
Table: devices
id | device_id | Company | Version | Revision |
-----------------------------------------------
1 | dev_a | Almaras | 1.5.1 | 0.2A |
2 | dev_b | Enigma | 1.5.1 | 0.2A |
3 | dev_c | Almaras | 1.5.1 | 0.2C |
*Field: device_id is Primary Key Unique String
*Field ID is just an auto-number column
Table: activities
id | act_id | act_date | act_type | act_note |
------------------------------------------------
1 | dev_a | 07/22/2013 | usb_axc | ok |
2 | dev_a | 07/23/2013 | usb_axe | ok | (LAST ROW for dev_a)
3 | dev_c | 07/22/2013 | usb_axc | ok | (LAST ROW for dev_c)
4 | dev_b | 07/21/2013 | usb_axc | ok | (LAST ROW for dev_b)
*Field: act_id contains device_id; NOT UNIQUE
*Field ID is just an auto-number column
Table: matrix
id | mat_id | tc | ts | bat | cycles |
-----------------------------------------
1 | dev_a | 2811 | 10 | 99 | 200 |
2 | dev_a | 2911 | 10 | 97 | 400 |
3 | dev_a | 3007 | 10 | 94 | 600 |
4 | dev_a | 3210 | 10 | 92 | 800 | (LAST ROW for dev_d)
5 | dev_b | 1100 | 5 | 98 | 100 |
6 | dev_b | 1300 | 8 | 93 | 200 |
7 | dev_b | 1411 | 11 | 90 | 300 | (LAST ROW for dev_b)
8 | dev_c | 4000 | 27 | 77 | 478 | (LAST ROW for dev_c)
*Field: mat_id contains device_id; NOT UNIQUE
*Field ID is just an auto-number column
Is there any way to query tables to get results as shown below (each device from devices and only last row added [see example output table] from each of the other two tables):
Query Results:
device_id | Company | act_date | act_type | bat | cycles |
------------------------------------------------------------
device_a | Almaras | 07/23/2013 | usb_axe | 92 | 800 |
device_b | Enigma | 07/21/2013 | usb_axc | 90 | 300 |
device_c | Almaras | 07/22/2013 | usb_axc | 77 | 478 |
Any ideas? Thank you in advance for reading and helping me out :)
I think is what you want,
SELECT a.device_id, a.Company,
b.act_date, b.act_type,
c.bat, c.cycles
FROM ((((devices AS a
INNER JOIN activities AS b
ON a.device_id = b.act_id)
INNER JOIN matrix AS c
ON a.device_id = c.mat_id)
INNER JOIN
(
SELECT act_id, MAX(act_date) AS max_date
FROM activities
GROUP BY act_id
) AS d ON b.act_id = d.act_id AND b.act_date = d.max_date)
INNER JOIN
(
SELECT mat_id, MAX(tc) AS max_tc
FROM matrix
GROUP BY mat_id
) AS e ON c.mat_id = e.mat_id AND c.tc = e.max_tc)
The subqueries: d and e separately gets the latest row for every act_id.
Try
SELECT devices.device_id, devices.Company, activities.act_data, activities.act_type, matrix.bat, matrix.cycles
FROM devices
LEFT JOIN activities
ON devices.device_id = activities.act_id
LEFT JOIN matrix
ON devices.device_id = matrix.mat_id;
What do you consider the "last" row in Matrix?
You need to do something like
WHERE act_date in (SELECT max(a.act_date) from activities a where a.mat_id=d.device_id GROUP BY a.mat_id)
and something similar for the join to matrix.

SQL Join with Group By

Ok, so i'm trying to write a complex query (at least complex to me) and need some pro help. This is my database setup:
Table: MakeList
| MakeListId | Make |
| 1 | Acura |
| 2 | Chevy |
| 3 | Pontiac |
| 4 | Scion |
| 5 | Toyota |
Table: CustomerMake
| CustomerMakeId | CustomerId | _Descriptor |
| 1 | 123 | Acura |
| 2 | 124 | Chevy |
| 3 | 125 | Pontiac |
| 4 | 126 | Scion |
| 5 | 127 | Toyota |
| 6 | 128 | Acura |
| 7 | 129 | Chevy |
| 8 | 130 | Pontiac |
| 9 | 131 | Scion |
| 10 | 132 | Toyota |
Table: Customer
| CustomerId | StatusId |
| 123 | 1 |
| 124 | 1 |
| 125 | 1 |
| 126 | 2 |
| 127 | 1 |
| 128 | 1 |
| 129 | 2 |
| 130 | 1 |
| 131 | 1 |
| 132 | 1 |
What i am trying to end up with is this...
Desired Result Set:
| Make | CustomerId|
| Acura | 123 |
| Chevy | 124 |
| Pontiac | 125 |
| Scion | 131 |
| Toyota | 127 |
I am wanting a list of unique Makes with one active (StatusId = 1) CustomerId to go with it. I'm assuming i'll have to do some GROUP BYs and JOINS but i haven't been able to figure it out. Any help would be greatly appreciated. Let me know if i haven't given enough info for my question. Thanks!
UPDATE: The script doesn't have to be performant - it will be used one time for testing purposes.
Something like this:
select cm._Descriptor,
min(cu.customerid)
from CustomerMake cm
join Customer cu on cuo.CustomerId = cm.CustomerId and cu.StatusId = 1
group by cm._Descriptor
I left out the MakeList table as it seems unnecessary because you are storing the full make name as _Descriptorin the CustomerMake table anyway (so the question is what is the MakeList table for? Why don't you store a FK to it in the CustomerMake table?)
You want to
(a) join the customer and customermake tables
(b) filter on customer.statusid
(c) group by customermake._descriptor
Depending on your RDBMS, you may need to explicitly apply a group function to customer.customerid to include it in the select list. Since you don't care which particular customerid is displayed, you could use MIN or MAX to just pick an essentially arbitrary value.