How can I select multiple copies of the same row? - sql

I have a table in MS Access with rows which have a column called "repeat"
I want to SELECT all the rows, duplicated by their "repeat" column value.
For example, if repeat is 4, then I should return 4 rows of the same values. If repeat is 1, then I should return only one row.
This is very similar to this answer:
https://stackoverflow.com/a/6608143
Except I need a solution for MS Access.

First create a "Numbers" table and fill it with numbers from 1 to 1000 (or up to whatever value the "Repeat" column can have):
CREATE TABLE Numbers
( i INT NOT NULL PRIMARY KEY
) ;
INSERT INTO Numbers
(i)
VALUES
(1), (2), ..., (1000) ;
then you can use this:
SELECT t.*
FROM TableX AS t
JOIN
Numbers AS n
ON n.i <= t.repeat ;

If repeat has only small values you can try:
select id, col1 from table where repeat > 0
union all
select id, col1 from table where repeat > 1
union all
select id, col1 from table where repeat > 2
union all
select id, col1 from table where repeat > 3
union all ....

What you can do is to retrieve the one 'unique' row and copy this row/column into a string however many copies you need from it using a for loop.

Related

How to add specific number of empty rows in sqlite?

I have a SQLite file and I want to add 2550 empty (NULL) rows.
I am able to add one empty line with this code
INSERT INTO my_table DEFAULT VALUES
But I need 2550 rows. Is there any shortcut for it? I don't want to execute same code 2550 times.
If your version of SQLite support it, you could use a recursive CTE to generate a series from 1 to 2550, and then insert "empty" records along that sequence:
WITH RECURSIVE generate_series(value) AS (
SELECT 1
UNION ALL
SELECT value + 1
FROM generate_series
WHERE value + 1 <= 2550
)
INSERT INTO yourTable (col1, col2, ...)
SELECT NULL, NULL, ...
FROM generate_series;
It is not clear which values, if any, you want to specify for the actual insert. If you omit mention of any column in the insert, then by default SQLite should assign NULL or whatever default value be defined for that column.
If your table is empty, then use a recursive CTE to get 2550 rows each consisting of the integers 1 to 2550 and use them to insert 2550 rows:
WITH cte AS (
SELECT 1 nr
UNION ALL
SELECT nr + 1
FROM cte
WHERE nr < 2550
)
INSERT INTO my_table(rowid)
SELECT nr FROM cte
This way, you use the column rowid where the integer values of the CTE will be stored and there is no need to enumerate all the columns of your table in the INSERT statement. These columns will get their default values.
If your table is not empty you can do it in a similar way by starting the integer numbers from the max rowid value in the table +1:
WITH cte AS (
SELECT MAX(rowid) + 1 nr FROM my_table
UNION ALL
SELECT nr + 1
FROM cte
WHERE nr < (SELECT MAX(rowid) + 2550 FROM my_table)
)
INSERT INTO my_table(rowid)
SELECT nr FROM cte
See a simplified demo (for 5 rows).
But since you also tagged android-sqlite you can use a for loop:
for (int i = 1; i <= 2550; i++) {
db.execSQL("INSERT INTO my_table DEFAULT VALUES");
}
where db is a valid non null instance of SQLiteDatabase.
You can generate numbers using a recursive CTE and then insert . . . but you need to be more explicit about the values being inserted:
with cte as (
select 1 as n
union all
select n + 1
from cte
where n < 2550
)
insert into mytable (<something>)
select <something>
from cte;
I think you need to specify the value for at least one column in SQLite.

Save value in local variable HANA SQL Script

I'm trying to take value from a non-empty row and overwrite it in the subsequent rows until another non-empty row appears and then write that in the subsequent rows. Coming from ABAP Background, I'm not sure how to accomplish this in HANA SQL Script. Here's a picture to show what the data looks like.
Basically 'Doe, John' should be overwritten into all the empty rows until 'Doe, Jane' appears and then 'Doe, Jane' should be overwritten into empty rows until another name appears.
My idea is to store the non-empty row in a local variable, but I haven't had much success so far. Here's my code:
tempTab1 = SELECT
CASE WHEN EMPLOYEE <> ''
THEN lv_emp = EMPLOYEE
ELSE EMPLOYEE
END AS EMPLOYEE,
FROM :tempTab;
In general, rows in dataset are unordered until you explicitly specify ORDER BY part of SQL. If you observe some order it may be a side-effect and can vary. So first of all you have to explicitly create a row number column (assume it's name is RECORD).
Then you should go this way:
Select only rows with non-empty data in column.
Use LEAD(RECORD) over(order by RECORD) to identify the next non-empty record number.
Join your source dataset to dataset defined on step 3 on between condition for RECORD field.
with a as (
select 1 as record, 'Val1' as field1 from dummy union
select 2 as record, '' as field1 from dummy union
select 3 as record, '' as field1 from dummy union
select 4 as record, 'Val2' as field1 from dummy union
select 5 as record, '' as field1 from dummy union
select 6 as record, '' from dummy union
select 7 as record, '' from dummy union
select 8 as record, 'Val3' as field1 from dummy
)
, fill_base as (
select field1, record, lead(record, 1, record) over(order by record asc) as next_record
from a
where field1 <> '' and field1 is not null
)
select
a.record
, case
when a.field1 = '' or a.field1 is null
then f.field1
else a.field1
end as field1
, a.field1 as field1_original
from a
left join fill_base as f
on a.record > f.record
and a.record < f.next_record
The performance in HANA may be bad in some cases since it process window functions very bad.
Here is another more elegant solution with two nested window functions than does not force you to write multiple selects for each column: How to make LAG() ignore NULLS in SQL Server?
You can use window aggregate function LAST_VALUE to achieve the imputation of missing values.
Sample Data
CREATE TABLE sample (id integer, sort integer, value varchar(10));
INSERT INTO sample VALUES (4711, 1, 'Hello');
INSERT INTO sample VALUES (4712, 2, null);
INSERT INTO sample VALUES (4713, 3, null);
INSERT INTO sample VALUES (4714, 4, 'World');
INSERT INTO sample VALUES (4715, 5, null);
INSERT INTO sample VALUES (4716, 6, '!');
Generate a new column with imputed values
SELECT base.*, LAST_VALUE(fill.value ORDER BY fill.sort) AS value_imputed
FROM sample base
LEFT JOIN sample fill ON fill.sort <= base.sort AND fill.value IS NOT NULL
GROUP BY base.id, base.sort, base.value
ORDER BY base.id, base.sort
Result
Note that sort could be anything determining the order (e.g. a timestamp).

Select or print column values that don’t exist between two integers

I have a list of about 10k sequential integer values that were supposed to be inserted into a table column from an external application. However, doing a COUNT() reveals that only 9900 were inserted.
I need to determine which of the numbers in the sequence were NOT inserted.
Using it the other way around is easy, just select from table column where value is BETWEEN x AND y, but I haven't figured out how to print (or select) the values that don't exist in the table column.
EDIT: remove extranous '' from integers below
SELECT * FROM table
WHERE column1 = 'value'
AND column2 BETWEEN 1 AND 10000
How can I print the value from the BETWEEN clause where column2 doesn't have value in range?
You could do something like:
select level num
from dual
connect by level <= 10000
minus
select column2
from your_table;
You may need to do to_char(level) if your column2 is a varchar2 column.
You need to use a source of numbers. If this table is your only data, you can use it:
with n as (
select rownum as n
from t cross join
(select 1 from dual union all select 2 from dual) x
)
select n.n
from n left join
t
on n.n = t.column2 and t.column1 = 'value'
where n <= 10000;
The calculation for n assumes that your table has at least 5,000 rows. If it has more than 10,000 then x is not necessary.

SQL clone/replicate records within same table with a condition

I have a table and i would like to replicate/clone records within the same table. However i would like to do that with a condition. And the condition is i have a column called recordcount with numeric values. For example Row 1 can take on a value of recordcount say 7, then i would like my row 1 to be replicated 7 times. Row 2 could take on a value say 9 then i would like row 2 to be replicated 9 times.
Any help is appreciated. Thank you
What you can do (and I'm pretty sure it's not a best practice),
Is to hold a table with just numbers, which has rowcount that correspond to the numeric value.
Join that with your table, and project your table only.
Example:
create table nums(x int);
insert into nums select 1;
insert into nums select 2;
insert into nums select 2;
insert into nums select 3;
insert into nums select 3;
insert into nums select 3;
create table t (txt varchar(10) , recordcount int);
insert into t select 'A',1;
insert into t select 'B',2;
insert into t select 'C',3;
select t.*
from t
inner join nums
on t.recordcount = nums.x
order by 1
;
Will project:
"A",1
"B",2
"B",2
"C",3
"C",3
"C",3

SELECT VALUES in Teradata

I know that it's possible in other SQL flavors (T-SQL) to "select" provided data without a table. Like:
SELECT *
FROM (VALUES (1,2), (3,4)) tbl
How can I do this using Teradata?
Teradata has strange syntax for this:
select t.*
from (select * from (select 1 as a, 2 as b) x
union all
select * from (select 3 as a, 4 as b) x
) t;
I don't have access to a TD system to test, but you might be able to remove one of the nested SELECTs from the answer above:
select x.*
from (
select 1 as a, 2 as b
union all
select 3 as a, 4 as b
) x
If you need to generate some random rows, you can always do a SELECT from a system table, like sys_calendar.calendar:
SELECT 1, 2
FROM sys_calendar.calendar
SAMPLE 10;
Updated example:
SELECT TOP 1000 -- Limit to 1000 rows (you can use SAMPLE too)
ROW_NUMBER() OVER() MyNum, -- Sequential numbering
MyNum MOD 7, -- Modulo operator
RANDOM(1,1000), -- Random number between 1,1000
HASHROW(MyNum) -- Rowhash value of given column(s)
FROM sys_calendar.calendar; -- Use as table to source rows
A couple notes:
make sure you pick a system table that will always be present and have rows
if you need more rows than are available in the source table, do a UNION to get more rows
you can always easily create a one-column table and populate it to whatever number of rows you want by INSERT/SELECT into it:
CREATE DummyTable (c1 INT); -- Create table
INSERT INTO DummyTable(1); -- Seed table
INSERT INTO DummyTable SELECT * FROM DummyTable; -- Run this to duplicate rows as many times are you want
Then use this table to create whatever resultset you want, similar to the query above with sys_calendar.calendar.
I don't have a TD system to test so you might get syntax errors...but that should give you a basic idea.
I am a bit late to this thread, but recently got the same error.
I solved this by simply using
select distinct 1 as a, 2 as b from DBC.tables
union all
select distinct 3 as a, 4 as b from DBC.tables
Here, DBC.tables is a DB backend table with a few rows only. So, the query runs fast as well