Group rows starting with same number into single row MS Access SQl - sql

I have an MS access table containing the following values
ID Value
1.1 5
1.2 5
1.3 2
2.1 3
2.2 1
2.3 9
Is there a way to get the sum of the values start start with the same ID (e.g. summ all values that start with 1 or 2)

You can extract the part to the left of the decimal:
select left(id, instr(id, '.') - 1), sum(value)
from t
group by left(id, instr(id, '.') - 1)

Assuming that ids are numbers (as they look like), you can use int() to extract their integer part, and aggregate by that:
select int(id) id, sum(value) sum_value from mytabel group by int(id)

Related

In SQL, how to combine two sequential rows into one when no common ID?

Have values split between multiple records without a key to join them. The order is sequential.
Current SQL table contents:
RowNum Value
1 10343
2 20784
3 34523
4 22415
5 31245
6 11345
7 24588
8 32946
I want to return rows combining the two consecutive records but only those with Values starting with 2 and 3. There is no common column value to group on.
Desired result:
RowNums Values
2-3 20784, 34523
4-5 22415, 31245
7-8 24588, 32946
You can use lead():
select concat(rownum, '-', next_rownum) as rownums,
concat(value, ', ', next_value) as values
from (select t.*,
lead(rownum) over (order by rownum) as next_rownum,
lead(value) over (order by value) as next_value
from t
) t
where value like '2%' and next_value like '3%';
This uses Standard SQL syntax. There might be variations depending on your database.

Sql how to have a repeating number until a certain number then starts over again

I have a table where I need to select data from it and add/create a column that counts up to 5 then keeps repeating until there are no more rows selected.
I essentially need an output that looks like the below:
ColumnName
1
2
3
4
5
1
2
3
4
5
... until all rows are returned.
You didn't specify the database engine. In Oracle you could use:
SELECT CASE MOD(ROWNUM, 5)
WHEN 0 THEN 5
ELSE MOD(ROWNUM, 5)
END AS ONE_TO_FIVE,
t.*
FROM YOUR_TABLE t
EDIT
Or you could use NVL and NULLIF:
SELECT NVL(NULLIF(MOD(ROWNUM, 5), 0), 5) AS ONE_TO_FIVE,
t.*
FROM YOUR_TABLE t
It seems like you want row_number() and modulo arithmetic. That would be something like this:
select 1 + ( (row_number() over (order by id) - 1) % 5)
from t;
id is any column in the table, particularly one that you would use for ordering the result set.
Note: Modulo arithmetic varies by databases. Some use mod() instead of %.
If you are utilizing a database engine with ROW_NUMBER function you can utilize that, and then take the modulo 5 of that value:
SELECT (ROW_NUMBER() + 1) % 5 OVER(),
other items
FROM ...
The above example is for SQL Server, as the DB engine is not specified ATM by OP.

SQL group table by "leading rows" without pl/sql

I have this table (short example) with two columns
1 a
2 a
3 a3
4 a
5 a
6 a6
7 a
8 a8
9 a
and I would like to group/partition them into groups separated by those leading "a", ideally to add another column like this, so I can address those groups easily.
1 a 0
2 a 0
3 a3 3
4 a 3
5 a 3
6 a6 6
7 a 6
8 a8 8
9 a 8
problem is that setup of the table is dynamic so I can't use staticly lag or lead functions, any ideas how to do this without pl/sql in postgres version 9.5
Assuming the leading part is a single character. Hence the expression right(data, -1) works to extract the group name. Adapt to your actual prefix.
The solution uses two window functions, which can't be nested. So we need a subquery or a CTE.
SELECT id, data
, COALESCE(first_value(grp) OVER (PARTITION BY grp_nr ORDER BY id), '0') AS grp
FROM (
SELECT *, NULLIF(right(data, -1), '') AS grp
, count(NULLIF(right(data, -1), '')) OVER (ORDER BY id) AS grp_nr
FROM tbl
) sub;
Produces your desired result exactly.
NULLIF(right(data, -1), '') to get the effective group name or NULL if none.
count() only counts non-null values, so we get a higher count for every new group in the subquery.
In the outer query, we take the first grp value per grp_nr as group name and default to '0' with COALESCE for the first group without name (which has a NULL as group name so far).
We could use min() or max() as outer window function as well, since there is only one non-null value per partition anyway. first_value() is probably cheapest since the rows are sorted already.
Note the group name grp is data type text. You may want to cast to integer, if those are clean (and reliably) integer numbers.
This can be achieved by setting rows containing a to a specific value and all the other rows to a different value. Then use a cumulative sum to get the desired number for the rows. The group number is set to the next number when a new value in the val column is encountered and all the proceeding rows with a will have the same group number as the one before and this continues.
I assume that you would need a distinct number for each group and the number doesn't matter.
select id, val, sum(ex) over(order by id) cm_sum
from (select t.*
,case when val = 'a' then 0 else 1 end ex
from t) x
The result for the query above with the data in question, would be
id val cm_sum
--------------
1 a 0
2 a 0
3 a3 1
4 a 1
5 a 1
6 a6 2
7 a 2
8 a8 3
9 a 3
With the given data, you can use a cumulative max:
select . . .,
coalesce(max(substr(col2, 2)) over (order by col1), 0)
If you don't strictly want the maximum, then it gets a bit more difficult. The ANSI solution is to use the IGNORE NULLs option on LAG(). However, Postgres does not (yet) support that. An alternative is:
select . . ., coalesce(substr(reft.col2, 2), 0)
from (select . . .,
max(case when col2 like 'a_%' then col1 end) over (order by col1) as ref_col1
from t
) tt join
t reft
on tt.ref_col1 = reft.col1
You can also try this :
with mytable as (select split_part(t,' ',1)::integer id,split_part(t,' ',2) myvalue
from (select unnest(string_to_array($$1 a;2 a;3 a3;4 a;5 a;6 a6;7 a;8 a8;9 a$$,
';'))t) a)
select id,myvalue,myresult from mytable join (
select COALESCE(NULLIF(substr(myvalue,2),''),'0') myresult,idmin id_down
,COALESCE(lead(idmin) over (order by myvalue),999999999999) id_up
from (
select myvalue,min(id) idmin from mytable group by 1
) a) b
on id between id_down and id_up-1

Grouping values based on sequence in SQL

Is there a way to create just using select statements a table that contains in a column the range of the repeating values like in this example?
Example:
from the input table:
id value:
1 25
2 25
3 24
4 25
5 25
6 25
7 28
8 28
9 11
should result:
range value
1-2 25
3-3 24
4-6 25
7-8 28
9-9 11
Note: The id values from the input table are always in order and the difference between 2 values ordered by id is always equal to 1
You want to find sequences of consecutive values. Here is one approach, using window functions:
select min(id), max(id), value
from (select id, value,
row_number() over (order by id) as rownum,
row_number() over (partition by value order by id) as seqnum
from t
) t
group by (rownum - seqnum), value;
This takes into account that a value might appear in different places among the rows. The idea is simple. rownum is a sequential number. seqnum is a sequential number that increments for a given value. The difference between these is constant for values that are in a row.
Let me add, if you actually want the expression as "1-2", we need more information. Assuming the id is a character string, one of the following would work, depending on the database:
select min(id)+'-'+max(id), . . .
select concat(min(id), '-', max(id)), . . .
select min(id)||'-'||max(id), . . .
If the id is an integer (as I suspect), then you need to replace the ids in the above expressions with cast(id as varchar(32)), except in Oracle, where you would use cast(id as varchar2(32)).
SELECT CONCAT(MIN(id), '-', MAX(id)) AS id_range, value
FROM input_table
GROUP BY value
Maybe this:
SELECT MIN(ID), MAX(ID), VALUE FROM TABLE GROUP BY VALUE

The minimum of 3 columns (phpmyAdmin SQL database)

I have 3 integer columns on the same table that I need to select only the minimum on a select
(price 1) (price 2) (price 3)
result1: 3 4 5
result2: 8 1 9
.
How I can get only the minimum number of each result?
I work with phpMyAdmin.
thanks
Use the least function
select result, least (price1,price2,price3) from yourtable
try this
select least('price1','price2','price3') from table1
SELECT LEAST(price1, price2, price3)
FROM Table