i have a table t1
id | names
----|-------------------------
1 | {jully , alex , sarah}
2 | {bety , cate , jenifer}
3 | {adam , pit , joee}
4 | {piter , mat , andy}
so, i need rows have at least one name that start with "a"
the result i need is in the below
in row 1 : alex
in row 3 : adam
in row 4 : andy
id | names
-----|-------------------------
1 | {jully , alex , sarah}
3 | {adam , pit , joee}
4 | {piter , mat , andy}
a query like it
select * from t1 where 'a' like% any t1.name
select *
from (
select id, unnest(names) as name
from t
) s
where name like 'a%';
id | name
----+------
1 | alex
3 | adam
4 | andy
To have it aggregated:
select id, array_agg(name)
from (
select id, unnest(names) as name
from t
) s
where name like 'a%'
group by id;
id | array_agg
----+-----------
4 | {andy}
1 | {alex}
3 | {adam}
And yet another solution using unnest
select * from t1
where exists (
select * from unnest(t1.names) n
where n like 'a%')
If you have to search multiple values inside the text array. You can use this:
SELECT * FROM t1 WHERE names && ARRAY['alex', 'jully'] ;
Related
I have 2 tables.
Table1
ID | String
1 | "A TEST B VALUE"
2 | "C TEST D DENT B"
Table 2
ID | Name | Value
1 | A | 1
1 | B | 2
2 | B | 3
2 | C | 4
2 | D | 5
The result I am hoping to get is
ID | String
1 | "1 TEST 2 VALUE"
2 | "4 TEST 5 5ENT 3"
I am trying to do this using with clause recursive
with QueryTable as (
select id, cast(String as nvarchar(max)) as 'String' ,1 as 'RN'
from [TABLE1]
group by id, String
union all
select a.id, cast(replace(a.String, b.Name, b.value) as nvarchar(max)) as 'Query', RN+1
from QueryTable a
inner join [TABLE2] b on a.id = b.id
)
Thank you so very much.
The solution Found in below link, so with cte recursive but compare between source and destination row num seem to solve the problem.
https://dba.stackexchange.com/questions/237182/how-to-replace-multiple-parts-of-a-string-with-data-from-multiple-rows
if anyone interested I can post the final solution
I'm using Snowflake and I'm hoping someone can help me understand how to count the number of unique names across columns for each row and overlook null values. Here is a sample of the data. So you can see below I'm looking to count the number of distinct values across the variables Name 1, Name 2, name 3, Name 4.
ID | Type | Name 1 | Name 2 | Name 3 | Name 4 | Expected result
1 | animal | cat | Dog | null | Dog | 2
2 | animal | fish | cat | cat | cat | 2
3 | animal | fish | cat | dog | rat | 4
You could use a unpivot approach:
SELECT ID, Type, COUNT(DISTINCT Name) AS cnt
FROM
(
SELECT ID, Type, Name1 AS Name FROM yourTable UNION ALL
SELECT ID, Type, Name2 FROM yourTable UNION ALL
SELECT ID, Type, Name3 FROM yourTable UNION ALL
SELECT ID, Type, Name4 FROM yourTable
) t
GROUP BY ID, Type;
Demo
This approach works by unpivoting the name data to a format where one record has just one ID and one name. Then, we aggregate and take the distinct count. The COUNT() function works well here, because by default it ignores NULL values, which is the behavior you want.
I have a table of a classroom with 3 column: Name, Class and Age. When do
Select * from students
It shows these value
Name | Class | Age
John | D | 7
Mary | A | 10
Jenny | B | 9
Peter | D | 7
I want to sort the values with these conditions
- First, Order by Age DESC
- If there are more 2 people have same age, Order by Name ASC
I use these command
Select * from students order by Age Desc, Name ASC .
but it doesn't sort Class too. Is there anyone can help me?
To sort by class first, then age, then name:
Select Name, Class, Age
FROM students
ORDER BY class ASC, Age DESC, Name ASC;
Should output:
Name | Class | Age
Mary | A | 10
Jenny | B | 9
John | D | 7
Peter | D | 7
To sort by age first, then class, then name:
Select Name, Class, Age
FROM students
ORDER BY Age DESC, class ASC, Name ASC;
Should output the same, because the data provided happens to sort the same way using this alternate criteria.
Name | Class | Age
Mary | A | 10
Jenny | B | 9
John | D | 7
Peter | D | 7
Try this Query.
First use Asc then second use Desc.
Select * from students order by Name ASC, Age Desc,
declare #tab table(Name varchar(30), Class char(1), Age int )
insert into #tab
select 'John' , 'D' , 7
union all
select 'Mary' , 'A' , 10
union all
select 'Jenny' , 'B' , 9
union all
select 'Peter' , 'D' , 7
select * from #tab order by Age desc,name asc
Name Class Age
Mary A 10
Jenny B 9
John D 7
Peter D 7
This is what my query looks like right now:
with allmembers (objectid, parentid, name, parentname, recursion) as
(
-- anchor elements: where parentid = 25
select objectid, parentid, name, name as parentname, 0 as recursion
from orgs as orgs1
where parentid = 25
-- recursion begins here
union all
select orgs2.objectid, orgs2.parentid, orgs2.name, orgs3.name as parentname, recursion + 1
from orgs as orgs2
join allmembers as orgs3 on orgs2.parentid = orgs3.objectid
)
-- we select all the results
select *
from allmembers
It selects the orgs (organizations) from a list, where the parentid is 25 (these are the "root organizations") and joins them with all their child organizations, recursively, until there are none left. So we get a list of organizations and their parents.
My problem is that I get only the direct child/parents relationsships:
name | parentname
Sales | All_Employees
Direct Sales | Sales
What is lost in this process is that "Direct Sales" is also a member of "All_Employees", indirectly, through "Sales".
So I would rather have the following result added:
name | parentname
Sales | All_Employees
Direct Sales | Sales
Direct Sales | All_Employees
How to achieve this?
Without going too far and getting functions involved, would using a materialized path suffice for your needs?
create table orgs (objectid int, name varchar(128), parentid int);
insert into orgs values
(26,'All Employees', 25)
,(27,'Sales', 26)
,(28,'Direct Sales',27);
with allmembers as (
-- anchor elements: where parentid = 25
select
objectid
, parentid
, name
, parentname = convert(varchar(128),'')
, rootname = name
, recursion = convert(int,0)
, name_path = convert(varchar(256),name)
from orgs
where parentid = 25
-- recursion begins here
union all
select
c.objectid
, c.parentid
, c.name
, parentname = p.name
, rootname = p.rootname
, recursion = p.recursion + 1
, name_path = convert(varchar(256),p.name_path + ' > ' + c.name)
from orgs as c
join allmembers as p on c.parentid = p.objectid
)
-- we select all the results
select *
from allmembers
returns:
+----------+----------+---------------+---------------+---------------+-----------+--------------------------------------+
| objectid | parentid | name | parentname | rootname | recursion | name_path |
+----------+----------+---------------+---------------+---------------+-----------+--------------------------------------+
| 26 | 25 | All Employees | | All Employees | 0 | All Employees |
| 27 | 26 | Sales | All Employees | All Employees | 1 | All Employees > Sales |
| 28 | 27 | Direct Sales | Sales | All Employees | 2 | All Employees > Sales > Direct Sales |
+----------+----------+---------------+---------------+---------------+-----------+--------------------------------------+
Say, I have 3 columns in my table :
---------------
name | ID | Amt
ABC | 1 | 500
ABC | 1 | 650
XYZ | 2 | 700
XYZ | 2 | 550
DEF | 3 | 200
how can I get an output where the amount is aggregated for each ID, i.e.,
ABC gives 1150, XYZ 1250 and DEF 200?
You want a group by, with what sounds like a sum from your example:
Select Name, ID, sum(amt) as TotalAmt
from MyTable
Group by Name, ID
SELECT name,SUM(Amt) FROM [table] GROUP BY name
or, if you want to display name and ID
SELECT name,ID,SUM(Amt) OVER (PARTITION BY name) FROM [table]
This could be done using a simple group by statement:
select name,
id,
sum(amt) as agg_sum
from total
group by name,id;
SQL Fiddle Demo