I need to reorder the values in rows of a table by alphabetical order, for example:
Id Values
--------------------------------
1 Banana, Apple, Oranges
2 Oranges, Melon, Cucumber
3 Cucumber, Banana, Apple
The expected output should be:
Id Values
--------------------------------
1 Apple, Banana, Oranges
2 Cucumber, Melon, Oranges
3 Apple, Banana, Cucumber
You can generate the data above using the following code:
CREATE TABLE [Table] (
[Id] INT NOT NULL,
[Values] VARCHAR(30) NOT NULL,
CONSTRAINT [PK_Table_Id] PRIMARY KEY CLUSTERED ([Id])
);
GO
INSERT INTO [Table] ([Id], [Values]) VALUES (1, 'Banana, Apple, Oranges'),(2, 'Oranges, Melon, Cucumber'),(3, 'Cucumber, Banana, Apple');
If you are using SQL Server 2017 or later, we can use a combination of STRING_SPLIT and STRING_AGG:
WITH cte AS (
SELECT Id, value
FROM [Table]
CROSS APPLY STRING_SPLIT([Values], ', ')
)
SELECT
Id,
STRING_AGG(value, ', ') WITHIN GROUP (ORDER BY value) AS [Values]
FROM cte
GROUP BY Id
ORDER BY Id;
However, I seriously suggest that you stop just with my CTE step above, because storing CSV values in your table is a bad idea from the very beginning. So, once you have each value per Id on a separate row, you should stop, because then your data is already normalized, or at least much closer to it.
Related
I am using the Coalesce function to return a value from my preferred ranking of Columns but I also want to include the name of the column that the value was derived from.
`i.e
Table:
Apples Pears Mangos
4 5
**SQL **
; with CTE as
(
Select
Coalesce(Apples,Pears,Mangos) as QTY_Fruit
from Table
) select *, column name from QTY_Fruit
from CTE
Result:
QTY_Fruit Col Name
4 Pears`
I am trying to avoid a case statement if possible because there are about 12 fields that I will need to use in my Coalesce. Would love for an easy way to pull the column name based on value in QTY_Fruit. I'm all ears if the answer lies outside the use of subqueries but I figured this would be a start.
So, I was working with GridDB NodeJs Connector, I know the query to find out the null values which shows the records/rows:
SELECT * FROM employees where employee_salary = NaN;
But I want to replace the null values of the column with the mean value of the column, in order to maintain the data consistency for data analysis. How do I do that in GridDB?
The Employee table looks like the following:
employee_id employee_salary first_name department
---------------+---------------+--------------+--------------
0 John Sales
1 60000 Lisa Development
2 45000 Richard Sales
3 50000 Lina Marketing
4 55000 Anderson Development
I am looking for the best way to store and retrieve an array of data. The solution I am currently implementing uses a many to many relationship as follows.
venue_themes
user_id style environment
A1A2 formal indoor
A2B2 formal outdoor
theme_setting_to_setting_enum
id user_id setting_enum_id
1 A1A2 1
2 A1A2 3
3 A2B2 1
4 A2B2 2
setting_enum
id value
1 garden
2 beach
3 golf course
4 backyard
The query I currently have is:
SELECT vt.user_id, vt.style, vt.environment, se.value FROM venue_themes vt JOIN theme_settings_to_setting_enum ts ON vt.user_id = ts.user_id JOIN setting_enum se ON ts.setting_enum_id = se.id GROUP BY vt.user_id, ts.id, se.id;
This works but it returns multiple rows with the same data other than my setting enum values.
An example return is :
user_id style environment value
AAAA formal indoor beach
AAAA formal indoor backyard
AAAA formal indoor tent
This is fine but seems excessive if I have many values. What I really want my data to look like is:
user_id style environment value
AAAA formal indoor beach, backyard, tent
Ideally I would have my values returned in an array or something similar so I don't have to build a function to manipulate the returned data.
You can remove se.id from the GROUP BY clause, and use STRING_AGG() to generate the CSV string:
SELECT vt.user_id, vt.style, vt.environment, STRING_AGG(se.value, ', ') se_values
FROM venue_themes vt
JOIN theme_settings_to_setting_enum ts ON vt.user_id = ts.user_id
JOIN setting_enum se ON ts.setting_enum_id = se.id
GROUP BY vt.user_id;
Assuming that user_id is the primary key of venue_themes, it is sufficient to have just this column in the GROUP BY clause (other columns of the table are fonctionnally dependent on the primary key).
You can control the order in which values are aggregated in the string with an ORDER BY clause:
STRING_AGG(se.value, ', ' ORDER BY se.id) se_values
If you want an array instead of a CSV string, then use ARRAY_AGG():
ARRAY_AGG(se.value, ', ' ORDER BY se.id) se_values
Table12
CustomerId CampaignID
1 1
1 2
2 3
1 3
4 2
4 4
5 5
val CustomerToCampaign = ((1,1),(1,2),(2,3),(1,3),(4,2),(4,4),(5,5))
Is it possible to write a query like
select CustomerId, CampaignID from Table12 where (CustomerId, CampaignID) in (CustomerToCampaign_1, CustomerToCampaign_2)
???
So the input is a tuple but the columns are not tuple but rather individual columns.
Sure, it's possible. But only on the clustering keys. That means I need to use something else as a partition key or "bucket." For this example, I'll assume that marketing campaigns are time sensitive and that we'll get a good distribution and easy of querying by using "month" as the bucket (partition).
CREATE TABLE stackoverflow.customertocampaign (
campaign_month int,
customer_id int,
campaign_id int,
customer_name text,
PRIMARY KEY (campaign_month, customer_id, campaign_id)
);
Now, I can INSERT the data described in your CustomerToCampaign variable. Then, this query works:
aploetz#cqlsh:stackoverflow> SELECT campaign_month, customer_id, campaign_id
FROM customertocampaign WHERE campaign_month=202004
AND (customer_id,campaign_id) = (1,2);
campaign_month | customer_id | campaign_id
----------------+-------------+-------------
202004 | 1 | 2
(1 rows)
I am trying to compare data in one column that is in two different tables. The two tables are a lot more columns, but for simplicity.....
CREATE TABLE A(
ID integer PRIMARY KEY AUTOINCREMENT,
name char(20)
);
CREATE TABLE B(
ID integer PRIMARY KEY AUTOINCREMENT,
name char(20)
);
INSERT INTO A(name) VALUES ('John Smith');
INSERT INTO A(name) VALUES ('J Doe');
INSERT INTO A(name) VALUES ('Jane Smith');
INSERT INTO B(name)VALUES('John Smith');
INSERT INTO B(name)VALUES('J. Doe');
INSERT INTO B(name)VALUES('jane smith');
Most of what I've found so far has been to find the differences between tables, but I haven't managed to find how to match up similar data. I am looking for something that will yield results like this:
Table A | Table B
John Smith | John Smith
Jane Smith | jane smith
J Doe | J. Doe
The following code matched up several names:
CREATE TABLE tblC (
tblAName char(20),
tblBName char(20)
);
INSERT INTO tblC ( tblAName, tblBName)
SELECT
tblA.name,
tblB.name
FROM tblA
LEFT JOIN on tblB WHERE tblA.name LIKE tblB.name;
However, I haven't figured out how to get the names that contain punctuation. This didn't work:
INSERT INTO tblC (tblAName, tblBName)
SELECT
tblA.name,
tblB.name
FROM tblA
LEFT JOIN on tblB WHERE tblA.name LIKE tblB.name
WHERE tblA.name LIKE "%Xxx%" OR "%X.%" tblB.name LIKE "%Xxx%" OR "%X.%";
To ignore certain characters, remove them with replace() before doing the comparisons. To ignore case, use LIKE, or COLLATE NOCASE:
SELECT A.name,
B.name
FROM A
JOIN B ON replace(A.name, '.', '') LIKE
replace(B.name, '.', '');