Combine Rows in Access SQL where fields are blank - sql

I have been looking to combine multiple rows of information into a single row to fill in blank spaces.
Id | name | value1 | value2 | value3
1 bob 3
1 bob 6
1 bob B
How do I get those 3 rows into a single row? It is a confirmed that they will fit perfectly where the blank values are, no values will overlap.
Id | name | value1 | value2 | value3
1 bob 3 B 6
I have come across nothing of much use in my research besides something called ConcatRelated which I could not modify to fit my needs. I also tried a group by statement which I couldn't get to work either. Any ideas? I am newer to Access and SQL in general.

How do I get those 3 rows into a single row?
Use a GROUP BY query to consolidate the 3 "bob" rows into one. And then you can include an aggregate function such as Max() to retrieve the non-blank rows for each of the valueX columns.
SELECT
y.Id,
y.name,
Max(y.value1) AS MaxOfvalue1,
Max(y.value2) AS MaxOfvalue2,
Max(y.value3) AS MaxOfvalue3
FROM YourTable AS y
GROUP BY
y.Id,
y.name;
If you want to reuse the original column name, valueX, instead of a MaxOfvalueX alias, enclose that name in square brackets ...
Max(y.value1) AS [value1]

Related

How to unnest two lists from two columns in BigQuery without cross product, as individual rows

I have a table in BigQuery, it has two columns, each column contains an array. for a given row, both columns will contain arrays of the same length, but that length can vary from row to row:
WITH tbl AS (
select ['a','b','c'] AS one, [1,2,3] as two
union all
select ['a','x'] AS two, [10,20] as two
)
select * from tbl
So the table will look like:
row | one | two
-----------------------
1 | [a,b,c] | [1,2,3]
2 | [a,x] | [10,20]
I would like to unnest in such a way that each row, in the new table, will have an element of an array from column1 and an corresponding element from column2. So from the table above, I am looking to get:
row | one | two
---------
1 | a | 1
2 | b | 2
3 | c | 3
4 | a | 10
5 | x | 20
Any help would be much appreciated! Thanks!
below is for BigQuery Standard SQL
#standardSQL
SELECT z.*
FROM `project.dataset.table` t,
UNNEST(ARRAY(
SELECT AS STRUCT one, two
FROM UNNEST(one) one WITH OFFSET
JOIN UNNEST(two) two WITH OFFSET
USING(OFFSET)
)
) z
You can test, play with above using sample data from your question - result will be
Row one two
1 a 1
2 b 2
3 c 3
4 a 10
5 x 20
I dont fully understand the syntax, could you please explain it?
Explanation:
Step 1
for each row in table below array is calculated
ARRAY(
SELECT AS STRUCT one, two
FROM UNNEST(one) one WITH OFFSET
JOIN UNNEST(two) two WITH OFFSET
USING(OFFSET)
)
Elements of this array are structs with respective value from two column - they are being matched with each other by JOIN'ing on their positions in initial arrays (OFFSET)
Step 2
Then this array gets UNNEST'ed and cross JOIN'ed with respective row in the table - and whole row is actually ignored and only that struct (z) is being brought into to the output
Step 3
And finally to output not a a struct but rather as a separate columns - z.* is used
Hope this helped :o)

Oracle SQL update statement where column starts with x

Let's say I have this data:
ID | NAME | FRUIT
--------------------------
1 | abc_v1 | apple
2 | abc_v2 | banana
3 | abc_v3 | cherry
4 | xyz_v1 | banana
5 | xyz_v2 | grape
6 | xyz_v3 | apple
For each row, I want to replace the value in the FRUIT column with whatever's in the FRUIT column for the row with the smallest ID where the first four characters of NAME are the same.
So since the first three rows all have a NAME that starts with "abc_", I want all three of those rows to have "apple" in the FRUIT column, since that's the value where ID is the lowest. Similarly, I want the last three rows to all have the value "banana" in the FRUIT column, which is the FRUIT value in row 4, the lowest ID where NAME starts with "xyz_".
My real table has 16K rows. Each has a unique ID, and each will have a NAME that starts with the same four characters as zero or more other rows.
In really bad pseudocode, I want something like this:
UPDATE MYTABLE SET FRUIT =
(SELECT FRUIT FROM MYTABLE WHERE ID =
(SELECT MIN(ID) FROM MYTABLE WHERE NAME LIKE
[some way to represent first four characters]%));
Can I do this in a single SQL update statement in Oracle? I'm stuck on the part I put in brackets above; I feel like I'll need a variable that loops through all the rows, which makes me think maybe I need a PL/SQL program.
Help is much appreciated. Thanks!
Assumming that id is a primary key in MYTABLE
MERGE INTO MYTABLE m
USING (
SELECT m.*,
first_value( fruit )
over (partition by substr(name,1,4) order by id ) As new_fruit
FROM MYTABLE m
) x
ON (x.id = m.id )
WHEN MATCHED THEN UPDATE SET m.fruit = x.new_fruit;

How to merge two column with same data type of a table into one column using PostgreSql

I have found lots of answer to merge two column into one, but I want something like below:
I have a table named A
id_one | id_two
---------------
1 | 3
3 | 9
3 | 6
I want to combine these two column into one like
id
----
1
3
9
6
use Union to combine the two column which also removes duplicates
select id_one from yourtable
union
select id_two from yourtable

How do I return rows in groups by certain values?

I want my query to return the rows of a table in groups where a column contains specific values. After I got the rows ordered in the groups I want to be able to order them by name.
Example Table
- Id - Name - Group
- 1 George Group_2_1
- 2 Alfred Group_2_2
- 3 Eric Group_3
- 4 Mary Group_1_2
- 5 Jon Group_1_1
I want them ordered by their group and after that ordered by their name
- Id - Name - Group
- 1 Jon Group_1_1
- 2 Mary Group_1_2
- 3 Alfred Group_2_2
- 4 George Group_2_1
- 5 Eric Group_3
I found this SQL-Query-Snippet
ORDER BY CASE WHEN Group LIKE '%Group_1%' THEN 1 ELSE 2 END, Group
but it is not enough. The result is only grouped by the first group (obviously) but I can't extend it to order the second group because it is in the same column.
Please don't get confused by the example.
I just want to be able to group certain rows and put them in front of the results. I want a result that has all rows containing group 1 in the top, containing group 2 in the middle and containing group 3 in the bottom.
The values are not "Group_1_1" or something like that. They are just some strings and I want certain strings to be always in the first row (group 1) and some always below group 1
The problem here seems to be that some of your group names have an extra underscore, otherwise you could just order by the Group and all would be good. You could probably do something like this to work around this?
WITH Data AS (
SELECT 'Group1_1' AS Value
UNION
SELECT 'Group_3_2' AS Value
UNION
SELECT 'Group_2_2' AS Value
UNION
SELECT 'Group_3_1' AS Value
)
SELECT * FROM Data ORDER BY CASE WHEN Value LIKE 'Group_%' THEN SUBSTRING(Value, 7, 10) ELSE SUBSTRING(Value, 6, 10) END;
Results:
Value
Group1_1
Group_2_2
Group_3_1
Group_3_2
---- EDIT ----
Okay, seeing as your example isn't really an "example" it sounds like you are going to need a really, REALLY long case statement. You could do something like this (using the original Group_1_1, Group_2_2 codes) that would extend to different values. The key is that a CASE statement works from left to right and a value is assigned to the first case that matches:
ORDER BY
CASE
WHEN [Group] = 'Group_1_1' THEN 1
WHEN [Group] = 'Group_1_2' THEN 2
WHEN [Group] LIKE 'Group_1_%' THEN 3
WHEN [Group] = 'Group_2_1' THEN 4
WHEN [Group] = 'Group_2_2' THEN 5
WHEN [Group] LIKE 'Group_2_%' THEN 6
etc.
END;
Obviously that's very generic and depends on what the actual values are in your database.
Edits for mssql
If there is ANY instance of 3 underscores then the following simply won't work. However if there is the possibility of Group_12_6 or Group_21_1 then this approach may be worth trying.
It removes Group_ or Group from the string, leaving 1_1 or 12_6 or 21_1 then it replaces the remaining underscore with . giving 1.1 or 12.6 or 21.1 and casts this to decimal.
All utterly dependent of the consistency of those group names.
SELECT
id
, name
, [Group]
FROM YourData
ORDER BY
CAST(REPLACE(REPLACE(REPLACE([Group], 'Group_', ''), 'Group', ''), '_', '.') AS decimal(12,3))
, name
I'm really hoping you do not have a column called [Group] but if you do it has to be referenced as [Group] or "Group". Test result:
| ID | NAME | GROUP |
|----|--------|-----------|
| 1 | Jon | Group_1_1 |
| 2 | Mary | Group_1_2 |
| 4 | George | Group_2_1 |
| 3 | Alfred | Group_2_2 |
| 5 | Eric | Group_3 |
see http://sqlfiddle.com/#!3/e95b07/1

Transforming a 2 column SQL table into 3 columns, column 3 lagged on 2

Here's my problem: I want to write a query (that goes into a larger query) that takes a table like this;
ID | DATE
A | 1
A | 2
A | 3
B | 1
B | 2
and so on, and transforms it into;
ID | DATE1 | DATE2
A | 1 | 2
A | 2 | 3
A | 3 | NOW
B | 1 | 2
B | 2 | NOW
Where the numbers are dates, and NOW() is always appended to the most recent date. Given free rein I would do this in Python, but unfortunately this goes into a larger query. We're using SyBase's SQL Anywhere 12, I think? I interact with the database using SQuirreL SQL.
I'm very stumped. I thought (SQL query to transform a list of numbers into 2 columns) would help, but I'm afraid I don't know enough to make it work. I was thinking of JOINing the table to itself, but I don't know how to SELECT for only the A-1-2 rows instead of the A-1-3 rows as well, for instance, or how to insert the NOW() value into it. Does anyone have any ideas?
I made a an sqlfiddle.com to outline a solution for your example. You were mentioning dates, but using integers so I chose to do an integer example, but it can be modified. I wrote it in postgresql so the coalesce() function can be substituted with nvl() or similar. Also, the parameter '0' can be substituted with any value, including now(), but you must change the data type of the "i" column in the table to be a date as well. Please let me know if you need further help on this.
select a.id, a.i, coalesce(min(b.i),'0') from
test a
left join test b on b.id=a.id and a.i<b.i
group by a.id,a.i
order by a.id, a.i
http://sqlfiddle.com/#!15/f1fba/6