How to query multiple rows into a single-line string result? - sql

Let's say we have this table named phrases and it has contents like so:
phrases
+----+--------+
| id | phrase |
+----+--------+
| 1 | the |
| 2 | quick |
| .. | ... |
| 8 | lazy |
| 9 | dog |
+----+--------+
Desired result
+---------------------------------------------+
| sentence |
+---------------------------------------------+
| the quick brown fox jumps over the lazy dog |
+---------------------------------------------+
What should be the query statement such that it would result into a single result string like the above?

You can use STRING_AGG with an empty delimiter, and probably with a sort order
SELECT STRING_AGG(phrase , '' ORDER BY id) as sentence
FROM phrases;

Related

How to get every first result of select query in loop iterating over array of strings?

I have a table (e.g. Users) in PostgreSQL database. Its size is relatively large (ca. 4 GB of data) and I would like to get a table/result consisting of single rows fulfilling the select query. This query shall be executed for each element in an array of strings (couple dozens of elements).
Example single select for one element:
SELECT * FROM "Users" WHERE "Surname" LIKE 'Smith%' LIMIT 1
Value between ' and %' should be an element of input array.
EDIT: It doesn't matter for me whether I get record no. 1 or 2 for LIKE 'Smith%'
How can I achieve this?
I tried to append query results to some array variable within FOREACH loop but with no success.
Example source table:
| Id | Name | Surname |
|---- |-------- |---------- |
| 1 | John | Smiths |
| 2 | Adam | Smith |
| 3 | George | Kowalsky |
| 4 | George | Kowalsky |
| 5 | Susan | Connor |
| 6 | Clare | Connory |
| 7 | Susan | Connor |
And for ['Smith', 'Connor'] the output is:
| Id | Name | Surname |
|----|-------|---------|
| 1 | John | Smiths |
| 5 | Susan | Connor |
In Postgres you can use the ANY operator to compare a single value to all values of an array. This also works with together with the LIKE operator.
SELECT *
FROM "Users"
WHERE "Surname" like ANY (array['Smith%', 'Connor%'])
Note that LIKE is case sensitive, if you don't want that, you can use ILIKE
This will show you the logic. Syntax is up to you.
where 1 = 2
start of loop
or surname like 'Array Element goes here%'
end of loop

Postgres: Find matching array or array that contains t

I'm using postgres 9.5 and have a table that looks something like this:
+----+--------------+-------------------------------+
| id | string_field | array_field |
|----+--------------+-------------------------------|
| 1 | string a | [apple, orange, banana, pear] |
| 2 | string b | [apple, orange, banana] |
| 3 | string c | [apple, orange] |
| 4 | string d | [apple, pear] |
| 5 | string e | [orange, apple] |
+----+--------------+-------------------------------+
Is it possible to query the DB for rows where array_field is, or contains [apple, orange, banana]? The results should return rows with id 1 and 2.
Try something like this:
where array_field #> ARRAY['apple', 'orange', 'banana']::varchar[]
Documentation

DBIx::Class : Resultset order_by based upon existence of a value in the list

I am using DBIx::Class and I have got a ResultSet. I like to re-order the ResultSet. I like to check a particular column "City" against a fix list of values ("London", "New York" "Tokyo") If city is found in the list of values I like to move that result to the top group. If city is not found, I like to move that result to the bottom group in the ResultSet.
ORDER BY expr might be what you're looking for.
For example, here a table:
mysql> select * from test;
+----+-----------+
| id | name |
+----+-----------+
| 1 | London |
| 2 | Paris |
| 3 | Tokio |
| 4 | Rome |
| 5 | Amsterdam |
+----+-----------+
Here the special ordering:
mysql> select * from test order by name = 'London' desc,
name = 'Paris' desc,
name = 'Amsterdam' desc;
+----+-----------+
| id | name |
+----+-----------+
| 1 | London |
| 2 | Paris |
| 5 | Amsterdam |
| 3 | Tokio |
| 4 | Rome |
+----+-----------+
Translating this into a ResultSet method:
$schema->resultset('Test')->search(
{},
{order_by => {-desc => q[name in ('London', 'New York', 'Tokyo')] }}
);
Something like:
#!/usr/bin/env perl
use strict;
use warnings;
my $what = shift or die;
my #ary = qw(alpha beta gamma);
unshift(#ary,$what) unless ( grep(/$what/,#ary) );
print "#ary\n";
1;
Run as:
./myscript omega

Ordering a varchar column in MySQL in an Excel-like manner

I have a varchar column with mixed data- strings, integers, decimals, blank strings, and null values. I'd like to sort the column the same way that Excel would, first sorting numbers and then sorting the strings. For example:
1
2
3
3.5
10
11
12
alan
bob
carl
(blank/null)
(blank/null)
I've tried doing something like 'ORDER BY my_column+0' which sorts the numbers correctly but not the strings. I was hoping someone might know of an efficient way to accomplish this.
MartinofD's suggestion works for the most part and if I expand on it a little bit I can get exactly what I want:
SELECT a FROM test
ORDER BY
a IS NULL OR a='',
a<>'0' AND a=0,
a+0,
a;
Pretty ugly though and I'm not sure if there are any better options.
That's because my_column+0 is equal for all strings (0).
Just use ORDER BY my_column+0, my_column
mysql> SELECT a FROM test ORDER BY a+0, a;
+-------+
| a |
+-------+
| NULL |
| alan |
| bob |
| carl |
| david |
| 1 |
| 2 |
| 3 |
| 3.5 |
| 10 |
| 11 |
| 12 |
+-------+
12 rows in set (0.00 sec)
If you strictly need the numbers to be above the strings, here's a solution (though I'm not sure how quick this will be on big tables):
mysql> SELECT a FROM test ORDER BY (a = CONCAT('', 0+a)) DESC, a+0, a;
+-------+
| a |
+-------+
| 1 |
| 2 |
| 3 |
| 3.5 |
| 10 |
| 11 |
| 12 |
| alan |
| bob |
| carl |
| david |
| NULL |
+-------+
12 rows in set (0.00 sec)
This works:
SELECT a FROM test ORDER BY a IS NULL OR a='', a<>'0' AND a=0, a+0, a;
Any more efficient/elegant solution would be welcome however.

Grouped string aggregation / LISTAGG for SQL Server

I'm sure this has been asked but I can't quite find the right search terms.
Given a schema like this:
| CarMakeID | CarMake
------------------------
| 1 | SuperCars
| 2 | MehCars
| CarMakeID | CarModelID | CarModel
-----------------------------------------
| 1 | 1 | Zoom
| 2 | 1 | Wow
| 3 | 1 | Awesome
| 4 | 2 | Mediocrity
| 5 | 2 | YoureSettling
I want to produce a dataset like this:
| CarMakeID | CarMake | CarModels
---------------------------------------------
| 1 | SuperCars | Zoom, Wow, Awesome
| 2 | MehCars | Mediocrity, YoureSettling
What do I do in place of 'AGG' for strings in SQL Server in the following style query?
SELECT *,
(SELECT AGG(CarModel)
FROM CarModels model
WHERE model.CarMakeID = make.CarMakeID
GROUP BY make.CarMakeID) as CarMakes
FROM CarMakes make
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
It is an interesting problem in Transact SQL, for which there are a number of solutions and considerable debate. How do you go about producing a summary result in which a distinguishing column from each row in each particular category is listed in a 'aggregate' column? A simple, and intuitive way of displaying data is surprisingly difficult to achieve. Anith Sen gives a summary of different ways, and offers words of caution over the one you choose...
If it is SQL Server 2017 or SQL Server VNext, Azure SQL database you can use String_agg as below:
SELECT make.CarMakeId, make.CarMake,
CarModels = string_agg(model.CarModel, ', ')
FROM CarModels model
INNER JOIN CarMakes make
ON model.CarMakeId = make.CarMakeId
GROUP BY make.CarMakeId, make.CarMake
Output:
+-----------+-----------+---------------------------+
| CarMakeId | CarMake | CarModels |
+-----------+-----------+---------------------------+
| 1 | SuperCars | Zoom, Wow, Awesome |
| 2 | MehCars | Mediocrity, YoureSettling |
+-----------+-----------+---------------------------+