This question already has answers here:
Need to query distinct combination of two fields, along with a count that distinct combination occurs
(2 answers)
Closed 3 years ago.
I have a table
table_user
col1 col2
123 456
124 457
125 458
126 459
127 460
128 461
123 456
123 456
123 457
I need to find out the combination of col1 and col2 with counts.
In above example:
col1 col2 count_combination
123 456 3
123 457 1
124 457 1
125 458 1
126 459 1
127 460 1
128 461 1
How can I find it?
With group by col1, col2:
select col1, col2, count(*) count_combination
from table_user
group by col1, col2
Simple aggregation would work :
select co1l, col2, count(*) as count_combination
from table_user
group by co1l, col2;
Related
I have a ORACLE sql query that needs to add a header (Only one row) with the name of the columns in the outcome.
How could that be achieved?
1-1-2022 08:32:00 xxx1 166 1 04641127 8 1
1-1-2022 07:05:00 xxx1 167 1 10205792 8 1
1-1-2022 09:20:00 xxx1 176 1 10256841 8 1
1-1-2022 10:10:00 xxx1 177 1 10193856 8 1
Regards
Date dep room nr rec type count
6-4-2022 08:32:00 xxx1 166 1 04641127 8 1
6-4-2022 07:05:00 xxx1 167 1 10205792 8 1
5-4-2022 09:20:00 xxx2 176 1 10256841 8 1
5-4-2022 10:10:00 xxx2 177 1 10193856 8 1
UNION is one option; note that - in that case - both SELECT statements have to share the same number of columns and their datatypes.
Something like this:
select 'Date' col1, 'dep' col2, 'room' col3, 'nr' col4, 'rec' col5, 'type' col6, 'count' col7
from dual
union all
select to_char(date_column, 'dd-mm-yyyy hh24:mi:ss'),
dep,
to_char(room),
to_char(nr),
rec,
to_char(type),
to_char(count_column)
from some_table
When I use
LAG(Static_Col_2, 1) OVER (ORDER BY Static_Col_1) AS LAGged_Col
I get these results:
Static_Col_1 Static_Col_2 LAGged_Col
----------------------------------------
1 456 NULL
2 457 456
3 458 457
4 459 458
5 460 459
5 461 460
5 462 461
But I want:
Static_Col_1 Static_Col_2 LAGged_Col
----------------------------------------
1 456 NULL
2 457 456
3 458 457
4 459 458
5 460 459
5 461 459
5 462 459
When '5' repeats the LAG should point to '4' every time.
I don't think you can do this in SQL Server with a simple window function. You can nest window functions or use a group by/join:
select t.*, tt.prev_col2
from t join
(select col1, lag(max(col2)) over (order by col1) as prev_col2
from t
group by col1
) tt
on t.col1 = tt.col1
order by 1;
Here is a db<>fiddle.
Table order_details:
order_id dish_id category_id
----------------------------------
601 22 123
601 23 234
603 32 456
603 54 456
603 11 543
603 19 456
From the sample table provided above: how can I group the order_id,dish_id and category_id on the basis of distinct group with respect to each order_id?
The result should look like
order_id dish_id category_id count
---------------------------------------------
601 22 123 1
601 23 234 1
603 32 456 3
603 54 452 3
603 11 543 3
603 19 456 3
Note:
Like dish_id 22 in order_id 601 went along with 1 different distinct category_id i.e 234, and similarly in order_id 603 dish_id 32 went along 2 different distinct category_id ie 456, 543
If I assume that the triplets are unique, you seem to want 1 less than the count of the group. That would be:
select t.*,
(count(*) over (partition by order_id) - 1) as cnt
from t;
I'm attempting to create group_ids based on a set of item_ids. The only indication that the item_ids are part of a single group is the fact that item_ids are sequential. For example, based on the first two columns below, the output I want is the third:
item item_id group_id
ABC 282 2
ABC 283 2
ABC 284 2
ABC 285 2
ABC 051 3
ABC 052 3
ABC 189 4
ABC 231 5
ABC 232 5
ABC 233 5
ABC 234 5
ABC 247 6
ABC 248 6
ABC 249 6
ABC 250 6
ABC 091 7
ABC 092 7
The group_id doesn't necessarily have to be sequential itself, it only has to be unique. I attempted this with the following code:
create sequence seq
start with 1
minvalue 1
increment by 1
cache 20;
select seq.nextval from dual; --to initialize the sequence
select
item,
item_id,
case when diff = 1 then seq.currval else seq.nextval end group_id
from
(
select
item,
item_id,
(id - lag(id, 1, 0) over (order by 1) diff
from
(
select
item,
item_id
from
table
)
);
But get the following output:
item item_id group_id
ABC 282 2
ABC 283 3
ABC 284 4
ABC 285 5
ABC 051 6
ABC 052 7
ABC 189 8
ABC 231 9
ABC 232 10
ABC 233 11
ABC 234 12
ABC 247 13
ABC 248 14
ABC 249 15
ABC 250 16
ABC 091 17
ABC 092 18
When looking for the cause of the problem, I found an excellent explanation by user ShannonSeverance that details why my solution won't work. However, it didn't provide any suggestions on how to move forward.
Does anyone have any ideas?
You have a problem, because SQL tables are inherently unordered. The following "should" logically work, although it won't in practice:
select ii.*, (item_id - rownum) as grp_id
from item_ids ii;
A sequence of item_ids in order minus the row number is constant. You can use that for a group, at least for a given item. To handle multiple items, concatenate the values together:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii;
To really make this work, you need to add an order by -- this guarantees the ordering of the results from the select. This might work, assuming that there are "holes" between the groups:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii
order by item, item_id;
Otherwise, you need some other column to determine the proper ordering for the items.
I have a table with an ID and multiple informative columns. Sometimes however, I can have multiple data for an ID, so I added a column called "Sequence". Here is a shortened example:
ID Sequence Name Tel Date Amount
124 1 Bob 873-4356 2001-02-03 10
124 2 Bob 873-4356 2002-03-12 7
124 3 Bob 873-4351 2006-07-08 24
125 1 John 983-4568 2007-02-01 3
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
So, I would like to obtain only these lines:
124 3 Bob 873-4351 2006-07-08 24
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
Anyone could give me a hand on how I could build a SQL query to do this ?
Thanks !
You can calculate the maximum sequence using group by. Then you can use join to get only the maximum in the original data.
Assuming your table is called t:
select t.*
from t join
(select id, MAX(sequence) as maxs
from t
group by id
) tmax
on t.id = tmax.id and
t.sequence = tmax.maxs