Merge Rows in Sql - sql-server-2008

I want to merge rows in SQL server as follows.
Table
PK F1 F2 F3 Order
A NULL NULL Grapes 2
B NULL Fig NULL 1
C Apple Orange Banana 0
The input and the expected result is as follows.
Input Expected Result
2 Apple Fig Grapes
1 Apple Fig Banana
0 Apple Orange Banana
How can I do this in sql stored procedure? I prefer to do in Sql other than in code.
Thanks in Advance

If I understand you input right then maybe something like this:
Test data
DECLARE #T TABLE
(
PK VARCHAR(5),
F1 VARCHAR(10),
F2 VARCHAR(10),
F3 VARCHAR(10),
[Order] INT
)
INSERT INTO #T
VALUES
('A',NULL,NULL,'Grapes',2),
('B',NULL,'Fig',NULL,1),
('C','Apple','Orange','Banana',0)
Query
;WITH CTE
AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY [Order]) AS RowNbr,
T.*
FROM
#T AS T
)
, CTE2
AS
(
SELECT
CTE.RowNbr,
CTE.PK,
CTE.F1,
CTE.F2,
CTE.F3,
CTE.[Order]
FROM
CTE
WHERE
CTE.RowNbr=1
UNION ALL
SELECT
CTE.RowNbr,
CTE.PK,
ISNULL(CTE.F1,CTE2.F1),
ISNULL(CTE.F2,CTE2.F2),
ISNULL(CTE.F3,CTE2.F3),
CTE.[Order]
FROM
CTE
JOIN CTE2 ON CTE.RowNbr=CTE2.RowNbr+1
)
SELECT
CTE2.[Order],CTE2.F1,CTE2.F2,CTE2.F3
FROM
CTE2
ORDER BY
CTE2.RowNbr DESC
Result
2 Apple Fig Grapes
1 Apple Fig Banana
0 Apple Orange Banana

Related

How to show count of records

I have the following data
ReasonId Team Division Location
2 A L1
3 B D1 L2
2 A D2 L1
2 A D3 L3
I want to show the count grouped by the ReasonId for each team,division & location. There could be instances where division could be null.
I am trying something like this,
SELECT
COUNT(*) AS TotalRequests, Reason, team
FROM
reports
GROUP BY Reason , team
UNION SELECT
COUNT(*) AS TotalRequests, Reason, location
FROM
reports
GROUP BY Reason , location
UNION SELECT
COUNT(*) AS TotalRequests, Reason, division
FROM
reports
WHERE
ISNULL(division) = 0
GROUP BY Reason , division
;
The output I am getting for the above is,
TotalRequests Reason team
1 2
3 2 A
1 3 B
1 3 D1
1 2 D2
1 2 D3
2 2 L1
1 3 L2
1 2 L3
Is it possible to get an output that looks like this,
ReasonId Team TotalByTeam Location TotalByLocation Division TotalByDivision
2 A 3 L1 2 0
2 A 3 L3 1 D2 1
2 A 3 L3 1 D3 1
3 B 1 L2 1 D1 1
I am using mysql 8.0.17 Here's a sample schema and dbfiddle of same
CREATE TABLE `reports` (
`Reason` int(11) DEFAULT NULL,
`Team` text,
`Division` text,
`Location` text
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO reports (Reason,Team,Division,Location) values (2, 'A',null,'L1');
INSERT INTO reports (Reason,Team,Division,Location) values (3, 'A','D1','L2');
INSERT INTO reports (Reason,Team,Division,Location) values (2, 'A','D2','L1');
INSERT INTO reports (Reason,Team,Division,Location) values (2, 'A','D3','L3');
You should use analytic functions COUNT(...) OVER (...) for this. They are available in MySQL since version 8.0.
select
reasonid,
team,
count(team) over (partition by team) as total_by_team,
location,
count(location) over (partition by location) as total_by_location,
division,
count(division) over (partition by division) as total_by_division
from reports;
Demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=79891554331e8222041ec34eea3fc4ee
Try this below script-
Demo Here
SELECT A.ReasonId,
A.Team,
(SELECT COUNT(*) FROM your_table B WHERE B.ReasonId = A.ReasonId AND B.Team = A.Team) TotalByTeam,
A.Division,
(SELECT COUNT(*) FROM your_table B WHERE B.ReasonId = A.ReasonId AND B.Division = A.Division) TotalByDivision,
A.Location,
(SELECT COUNT(*) FROM your_table B WHERE B.ReasonId = A.ReasonId AND B.Location = A.Location) TotalByLocation
FROM your_table A

Select duplicates while concatenating every one except the first

I am trying to write a query that will select all of the numbers in my table, but those numbers with duplicates i want to append something on the end that shows it as a duplicate. However I am not sure how to do this.
Here is an example of the table
TableA
ID Number
1 1
2 2
3 2
4 3
5 4
SELECT statement output would be like this.
Number
1
2
2-dup
3
4
Any insight on this would be appreciated.
if you mysql version didn't support window function. you can try to write a subquery to make row_number then use CASE WHEN to judgement rn > 1 then mark dup.
create table T (ID int, Number int);
INSERT INTO T VALUES (1,1);
INSERT INTO T VALUES (2,2);
INSERT INTO T VALUES (3,2);
INSERT INTO T VALUES (4,3);
INSERT INTO T VALUES (5,4);
Query 1:
select t1.id,
(CASE WHEN rn > 1 then CONCAT(Number,'-dup') ELSE Number END) Number
from (
SELECT *,(SELECT COUNT(*)
FROM T tt
where tt.Number = t1.Number and tt.id <= t1.id
) rn
FROM T t1
)t1
Results:
| id | Number |
|----|--------|
| 1 | 1 |
| 2 | 2 |
| 3 | 2-dup |
| 4 | 3 |
| 5 | 4 |
If you can use window function you can use row_number with window function to make rownumber by Number.
select t1.id,
(CASE WHEN rn > 1 then CONCAT(Number,'-dup') ELSE Number END) Number
from (
SELECT *,row_number() over(partition by Number order by id) rn
FROM T t1
)t1
sqlfiddle
I made a list of all the IDs that weren't dups (left join select) and then compared them to the entire list(case when):
select
case when a.id <> b.min_id then cast(a.Number as varchar(6)) + '-dup' else cast(a.Number as varchar(6)) end as Number
from table_a
left join (select MIN(b.id) min_id, Number from table_a b group by b.number)b on b.number = a.number
I did this in MS SQL 2016, hope it works for you.
This creates the table used:
insert into table_a (ID, Number)
select 1,1
union all
select 2,2
union all
select 3,2
union all
select 4,3
union all
select 5,4

Need MYSQL Query to select specific child rows only

FX., Given tables for baskets and fruits, looking for a query that returns the basket_id that contains ONLY the two specific fruit.
EX
table: fruits
basket_id | fruit
_________________
1 | apple
1 | orange
1 | pear
2 | apple
2 | orange
3 | apple
3 | pear
Given the above table, I'm looking for a query that returns the basket_id that ONLY contains the fruits "apple" and "orange", which would be row 2 only. Basket id 1 should be excluded because it also contains "pear".
Help with this would be most appreciated.
Please note for the example table, I added one more basket which is basket_id = 4, that has two apples only, and it will be a strong test sample for the query.
WITH ABC --sample table
AS
(
SELECT 1 as basket_id, 'Apple' as fruit
UNION ALL
SELECT 1 as basket_id, 'Orange' as fruit
UNION ALL
SELECT 1 as basket_id, 'Pear' as fruit
UNION ALL
SELECT 2 as basket_id, 'Apple' as fruit
UNION ALL
SELECT 2 as basket_id, 'Orange' as fruit
UNION ALL
SELECT 3 as basket_id, 'Apple' as fruit
UNION ALL
SELECT 3 as basket_id, 'Pear' as fruit
UNION ALL
SELECT 4 as basket_id, 'Apple' as fruit
UNION ALL
SELECT 4 as basket_id, 'Apple' as fruit
)
--main query:
SELECT basket_id FROM
(
SELECT *,CASE WHEN fruit in ('Apple','Orange') THEN 1 ELSE 0 END AS row_check
FROM ABC
) as A
GROUP BY basket_id
HAVING COUNT(DISTINCT row_check) =1 -- make sure there is no other fruit
AND COUNT(DISTINCT fruit) >1 -- make sure there are at least one apple and one orange
output: basket_id 2
select
f.basket_id,
(select count(1) from fruits where basket_id = f.basket_id) as fruits_in_basket,
(select count(1) from fruits where basket_id = f.basket_id and fruit in ("apple", "orange")) as specific_fruits_in_basket
from
fruits as f
group by f.basket_id
having fruits_in_basket = specific_fruits_in_basket
Here is a fiddle: http://sqlfiddle.com/#!9/f4ae3c/37/0
SELECT DISTINCT basket_id
FROM fruits f
WHERE
NOT EXISTS (SELECT 1 FROM fruits f1 WHERE f.basket_id=f1.basket_id AND f1.fruit NOT IN ('apple', 'orange'))
AND
(SELECT count(*) FROM fruits f2 WHERE f.basket_id=f2.basket_id AND f2.fruit='apple')=1
AND
(SELECT count(*) FROM fruits f3 WHERE f.basket_id=f3.basket_id AND f3.fruit='orange')=1;
I have tested the query on your example. Demo
If it is possible to use the list of items as an ordered list you want to select like 'apple,orange', then you can use following.
SELECT f.basket_id, f.fruit
FROM fruits f
INNER JOIN (
SELECT basket_id, GROUP_CONCAT(fruit order by fruit) as a
FROM fruits
GROUP BY basket_id
HAVING a = 'apple,orange'
) f1 ON f.basket_id = f1.basket_id
Here is the fiddle.
SELECT DISTINCT(basket_id)
FROM basket
where fruit IN ('apple', 'orange');

Querying with SQL

I am trying to write a query in sql which gives me distinct Pan details and the count of that Pan in the table where the Name is appearing more than once
For example: Consider the table below
ID Name Pan
1 ABC 123
2 ABC 123
3 DEF 456
4 ABC 124
5 WW 234
6 WW 2345
The result expected is :
Pan Name Count1
123 ABC 2
124 ABC 1
234 WW 1
2345 WW 1
Could someone please help me out with this.
Try this. Hope below statement help you out.
SELECT PAN, NAME , COUNT(ID) FROM TAB_PAN GROUP BY PAN, NAME HAVING COUNT(ID)>1
As per conversation the requirement seems different.
The below code will work fine.
Schema for given data
SELECT * INTO #TAB FROM (
SELECT 1 ID , 'ABC' NAME , 123 PAN
UNION ALL
SELECT 2, 'ABC', 123
UNION ALL
SELECT 3 , 'DEF' ,456
UNION ALL
SELECT 4 , 'ABC', 124
UNION ALL
SELECT 5 , 'WW' , 234
UNION ALL
SELECT 6 , 'WW' ,2345
)AS A
Logic for the required case
SELECT PAN, NAME,COUNT(ID) ACTUAL_COUNT FROM #TAB t
WHERE (SELECT COUNt(NAME) FROM #TAB WHERE NAME= t.NAME) >1
GROUP BY PAN, NAME
SELECT DISTINCT x.*
FROM
( SELECT pan
, name
, COUNT(*) total
FROM my_table
GROUP
BY pan
, name
) x
JOIN my_table y
ON y.name = x.name
AND y.pan <> x.pan

how to convert rows to columns in SQL Server 2008

I have a Table
F1 F2
-----------------
name Happy
Company a
City Gurgaon
name Deepak
Company b
City Delhi
I need the output as -
name company city
-----------------------
Happy a Gurgaon
Deepak b Delhi
I am using the query
SELECT
CASE WHEN F1='name'
THEN F2 ELSE NULL END) AS name,
CASE WHEN F1='Company'
THEN F2 ELSE NULL END) AS Company,
CASE WHEN F1='City'
THEN F2 ELSE NULL END) AS city
FROM table1
but I am getting the output as :
name company city
-----------------------------
Happy
a
Gurgaon
Deepak
b
Delhi
Can someone help please? I do not want to use PIVOT. Can this be achieved using inner join
Create a table to insert the elements with identity field
CREATE TABLE #TEMP(ID INT IDENTITY(1,1), F1 VARCHAR(20), F2 VARCHAR(20))
INSERT INTO #TEMP
SELECT * FROM
(
SELECT 'name' F1, 'Happy' F2
UNION ALL
SELECT 'Company', 'a'
UNION ALL
SELECT 'City', 'Gurgaon'
UNION ALL
SELECT 'name', 'Deepak'
UNION ALL
SELECT 'Company', 'b'
UNION ALL
SELECT 'City', 'Delhi'
)TAB
Since you don't have an Id for each set, we need to generate separate Id after every 3 records
and pivot according to that Id.
SELECT name, Company,City
FROM
(
-- Generate seperate Id after every 3 records
SELECT F1,F2,CAST((ID/3.5)AS INT)+1 RNO
FROM #TEMP
)P
PIVOT(MIN(F2)
FOR F1 IN (name, Company,City)) AS PVTTable
RESULT