Group by value extracted from function - sql

I am trying to group by a value extracted from a function. [fnSplitter] extracts the second delimiter from "123-456-459-905". In other words, it extracts "456". I alias the second delimiter as [Col_B] and I would like to group by it. Is this possible?
select
(
select data
from [fnSpliter] (REPLACE ((REPLACE (pk, '-', '|')),'||', '|-'), '|')
where id = 2
) as [Col_B]
from [Table]
group by [Col_B]

You can't group by an alias. So se apply:
select f.data as col_b
from [Table] t cross apply
[fnSpliter](REPLACE(REPLACE(pk, '-', '|'), '||', '|-'), '|') f
where f.id = 2
group by f.data

Assuming that you have a scalar function, as your question suggests, you could select the values in a subquery, than group by in the outer query:
select [Col_B]
from (
select dbo.[fnSpliter](REPLACE ((REPLACE (pk, '-', '|')),'||', '|-'), '|') as [Col_B]
from [Table]
where id = 2
) t
group by [Col_B]
Note that the name of the function should be prefixed with the schema it belongs to - I assumed dbo.
The example hardly makes sense. In a real query, you would likely use an aggregate function in the outer query (such as COUNT(*) for example).

Related

SQL: Count of items in comma-separated column in a table

Column1
--------
1,2,4
2,3,5
2,1,3
I have a column in a table which is comma-separated as shown above. From which I need to get below output:
No Count
----------
1 2
2 3
3 2
4 1
When I tried with
SELECT SUM(LEN(Holidays) - LEN(REPLACE(Holidays, ',', '')) + 1)
FROM [dbo].[OhLog]
I'm not getting item wise count. Instead it is getting full count.
You can use CROSS_APPLY with STRING_SPLIT to create rows from the comma separated data values, and then COUNT the occurrences of each value:
SELECT value as [Holiday], COUNT(*) AS [Count]
FROM OhLog
CROSS APPLY STRING_SPLIT([Holidays], ',')
GROUP BY value
Output:
Holiday Count
1 2
2 3
3 2
4 1
5 1
Demo on dbfiddle
If your database compatibility version is not at least 130, you won't have access to STRING_SPLIT. You can modify the compatibility version as described in the manual, or alternatively, use this query (based on this answer):
SELECT [Holiday], COUNT(*) AS [Count]
FROM (SELECT Split.a.value('.', 'NVARCHAR(MAX)') [Holiday]
FROM (SELECT CAST('<X>'+REPLACE([Holidays], ',', '</X><X>')+'</X>' AS XML) AS String
FROM Ohlog
) AS A
CROSS APPLY String.nodes('/X') AS Split(a)) AS O
GROUP BY [Holiday]
Output is the same as for the prior query. Demo on dbfiddle
Please try:
SELECT
Num, count(*) Cnt from
(
SELECT
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Num
FROM
(
SELECT CAST('<XMLRoot><RowData>' + REPLACE(Column1,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM tbl
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
)x
GROUP BY Num
Demo Result
So, you can use STRING_SPLIT function. It is supported by Sql Server 2017.
more info here http://www.sqlservertutorial.net/sql-server-string-functions/sql-server-string_split-function/
It creates a table from string.
So, for each row in DB you will get a table. To Union it into one common table you have to use CROSS APPLY.
SELECT VALUE, COUNT(*) FROM test_for_parse CROSS APPLY STRING_SPLIT(array_value,',') GROUP BY VALUE
So, here is an example of code, that emulate your situation.
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=8393f8dab667b528ed5aad7c61da74fe

How to find substrings in SQL (Postgres)

Let's say I have a column called 'code' in my database table containing string data types.
I want a query that will return all rows with a 'code' value that is a substring of a given search string, with the added condition that the substring appears at the end of the search string.
For example, if the search string is '12345', the query should return all rows with a 'code' value of:
12345
2345
345
45
5
Simply use like operator:
SELECT * from yourtable
where '12345' like '%' || Code
You can use a recursive CTE:
with recursive cte as (
select code
from yourtable t
union all
select substring(code, 2)
from cte
where code > ''
)
select *
from cte;
Or, you could use a lateral join and generate_series():
select substring(code, i)
from t cross join lateral
generate_series(1, length(code)) gs(i)

Convert from single column to multiple Column in sql Server

i have tried with below code. but i didnt get ouput as per multiple column.
select Name=stuff((select ','+
name from Input t1 WHERE t1.Name=t2.name for xml path('')),1,9,''),NAME
=stuff((select ','+
name from Input t1 WHERE t1.Name=t2.name for xml path('')),1,1,'')FROM
Input T2
GROUP BY NAME
I have separated the character and numeric parts of the given string in CTE and used a simple group by and sum clause on that.
;With CTE
As
(
Select
Left(Names, 1) As String,
SUBSTRING(Names, 2, Len(Names) - 1) As Number
From SeparateColumns
)
Select
String,
Sum(Cast(Number As Int)) As SumOfDigits
From CTE
Group By String
Order By String;
Assuming you will have single character in your column, the following code works
CREATE TABLE #TEMP_SPLIT
(VALUE VARCHAR(25))
INSERT INTO #TEMP_SPLIT
SELECT 'A10'
UNION
SELECT 'B20'
UNION
SELECT 'A30'
UNION
SELECT 'B40'
UNION
SELECT 'A10'
UNION
SELECT 'C1'
SELECT c, sum(tot)
FROM
(
SELECT SUBSTRING(VALUE,1,1) c ,CONVERT(FLOAT,SUBSTRING(VALUE,2,LEN (VALUE)-1)) Tot
FROM #TEMP_SPLIT
)T
GROUP BY C
DROP TABLE #TEMP_SPLIT
If the names column is always in the specified format, then use LEFT function to extract the character part and RIGHT function to extract the digits part and use these two in the sub-query and use GROUP BY clause and SUM function.
Query
select t.col_a as [string character],
sum(cast(t.col_b as int)) as [sum of digits] from(
select left(names, 1) as col_a,
right(names, len(names) - 1) as col_b
from [your_table_name]
) t
group by t.col_a;
Find a example here
You could use PATINDEX() with SUBSTRING() function if names always in this specified format
select A.CHAR [Strings], SUM(CAST(A.VALUE AS INT)) [Sum] from
(
SELECT SUBSTRING(Name, 1, PATINDEX('%[^A-Z]%', Name)-1) [CHAR], SUBSTRING(Name, PATINDEX('%[0-9]%', Name), len(Name)) [VALUE] FROM <table>
) a GROUP BY A.CHAR
Here's simple solution using subquery and group by clause:
select [StringChar], SUM([Number]) from (
select SUBSTRING(Names, 1, 1) as [StringChar],
convert(int, SUBSTRING(Names, 2, LEN(Names))) as [Number]
from [Input]
) as a group by [StringChar]

How can i use the replace statement in query

I am trying to query a table that has values separated by commas as follows:
SELECT ID, NAME,FULLNAME,STATUS,STORE
FROM EMPLOYEE
WHERE STORE IN (SELECT '''' + REPLACE('001,002',',',''',''') +'''')
ORDER BY STORE
when I run the query above, it produces no results,
but when I run it like this:
SELECT ID, NAME,FULLNAME,STATUS,STORE
FROM EMPLOYEE
WHERE STORE IN ('001','002')
ORDER BY STORE
I get like 500 records.
And when I try this:
SELECT ('''' + REPLACE('001,002',',',''',''') +'''')
I get the result '001','002'
so my question is, why the first script does not work, and produces no results?
Is there something I must add to the script for it to work?
please advise.
What if I had this scenario
SELECT ID, NAME,FULLNAME,STATUS,STORE
FROM dbo.EMPLOYEE
WHERE STORE IN (
SELECT t2.ID
FROM (
SELECT Value = REPLACE('001,002', ',', '.')
) t
CROSS APPLY (
VALUES
(PARSENAME(t.Value, 1)),
(PARSENAME(t.Value, 2))
) t2 (ID)
)
AND STATUS IN (
SELECT t2.ID1
FROM (
SELECT Value1 = REPLACE('A,T,L', ',', '.')
) t1
CROSS APPLY (
VALUES
(PARSENAME(t1.Value1, 1)),
(PARSENAME(t1.Value1, 2))
) t2 (ID1)
)
ORDER BY STORE
I tried that, and it didn't work, so I am just wondering if it works for more than 1 condition.

How to show query result in group? SQL Query

Right now my sql query display the result as follows.
though it is the correct result.
I prefer to have the have the result to show as follows.
How can I do this with SQL ? I am on SQL server 2008
I'm with the commenters, better to do this elsewhere, but it's simple enough in SQL using a CASE statement and the ROW_NUMBER() function:
;WITH cte AS (SELECT *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY (SELECT 1)) RN
FROM YourTable)
SELECT CASE WHEN RN = 1 THEN CAST(ID AS VARCHAR(5)) ELSE '' END, Name
FROM cte
ORDER BY ID,RN
Demo: SQL Fiddle
This is not a job for SQL.
Any way, you can easily display it with comma separated values:
ID Names
1000 Honda, Toyota,...
1000 Honda, Toyota,...
SELECT ID, Names=
STUFF((SELECT ', ' + Name
FROM your_table b
WHERE b.ID= a.ID
FOR XML PATH('')), 1, 2, '')
FROM your_table a
GROUP BY ID