SQL data convert column to row values - sql

I have a table with only one column about 100 rows of only names. But I need to display the 3 names in a row. So that I will get 34 rows each row with 3 names.
Example:
Name
_____
Raj
Sam
Guru
Tej
Avin
Sami
Fanst
I need to display above data as
Name Name1 Name2
____ _____ ______
Raj Sam Guru
Tej Avin Sami
Fanst
No condition just need to covert single column value into 3 columns data.
Oracle DB

You can do this using conditional aggregation and rownum. Something like this:
select max(case when mod(rn, 3) = 1 then name end) as name1,
max(case when mod(rn, 3) = 2 then name end) as name2,
max(case when mod(rn, 3) = 0 then name end) as name3
from (select name, rownum as rn
from table t
) t
group by trunc((rn - 1) / 3);

You can do it using CASE, make a try on it using PIVOT
Try to PIVOT Your Name column like this
SELECT Name,Name1,Name2
FROM
(SELECT Name FROM table_name) AS SourceTable
PIVOT
(
FOR Name IN (Name,Name1,Name2)
) AS PivotTable;

Related

SQL SELECT COUNT with Multiple WHERE conditions and based on MAX value of one column

I am trying to count number of columns contain specific text based on multiple WHERE LIKE condition for MAX value only.
ID
Name
Text
Value
1
Al
New
1
2
Al
NA
2
3
Al
NA
3
4
Al
NA
3
5
BK
New
1
9
BK
Old
2
7
BK
NA
3
I want to COUNT following (All rows WHERE Names is Like Al and Text is New only or rows which has the max value in this example value of 3):
The results for the above table should be 2 as there are two lines which meets the criteria.
ID
Name
Text
Value
3
Al
NA
3
4
Al
NA
3
SELECT COUNT(Text) AS NA WHERE Name LIKE 'AL' AND Text LIKE 'NA' AND Max(Value)
I know the above query is totally wrong but I am trying to explain what I am looking for.
You need a subquery for the max value:
select count(*)
from mytable
where name = 'Al' and text = 'NA' and value = (select max(value) from mytable);
Perhaps a CTE with DENSE_RANK and then a COUNT?
WITH CTE AS(
SELECT ID,
Name,
Text,
Value,
DENSE_RANK() OVER (PARTITION BY Name ORDER BY [Value] DESC) AS DR
FROM(VALUES(1,'Al','New',1),
(2,'Al','NA',2),
(3,'Al','NA',3),
(4,'Al','NA',3),
(5,'BK','New',1),
(9,'BK','Old',2),
(7,'BK','NA',3))V(ID,Name,Text,Value)
WHERE Name = 'Al'
AND Text = 'NA')
SELECT COUNT(*)
FROM CTE
WHERE DR = 1;

SQL UPDATE on the same table with WHERE

I have the following table and I want to fill up the empty values of the name column with the same value of the name where id_lang=2.
Any idea of what the sql query should be?
id_product
id_lang
name
1
1
-
1
2
name1
2
1
-
2
2
name2
3
1
-
3
2
name3
4
1
-
4
2
name4
One general approach which should work uses a correlated subquery:
UPDATE yourTable t1
SET name = (SELECT name FROM yourTable t2
WHERE t2.id_product = t1.id_product AND t2.id_lang = 2)
WHERE
name IS NULL;
In a query, you can simply use window function:
select t.*,
coalesce(name,
max(case when id_lang = 2 then name end) over (partition by id_product)
) as imputed_name
from t;
Note: This assumes that - really means NULL. If it is a string, the above can be tweaked to use CASE.
You can easily do this in an update as well, if you want to change the data in the table. However, the best way to do that depends on the database.
You can use a subquery: UPDATE table SET name = (SELECT DISTINCT name FROM table WHERE id_lang = 2)

How to select rows with condition? sql, select sentence

I have table like this:
NAME IDENTIFICATIONR SCORE
JOHN DB 10
JOHN IT NULL
KAL DB 9
HENRY KK 3
KAL DB 10
HENRY IP 9
ALI IG 10
ALI PA 9
And with select sentence I want that my result would be like only those names whose scores are 9 or above. So basically it means, that, for exaple, Henry cannot be selected, because he has score under the value of 9 in one line , but in the other he has the score of 3 (null values also should be emitted).
My newtable should look like this:
NAME
KAL
ALI
I'm using a sas program. THANK YOU!!
The COUNT of names will be <> COUNT of scores if there is a missing score. Requesting equality in the having clause will ensure no person with a missing score is in your result set.
proc sql;
create table want as
select distinct name from have
group by name
having count(name) = count(score) and min(score) >= 9;
here the solution
select name
from table name where score >= 9
and score <> NULL;
Select NAME from YOUR_TABLE_NAME name where SCORE > 9 and score is not null
You can do aggregation :
select name
from table t
group by name
having sum(case when (score < 9 or score is null) then 1 else 0 end) = 0;
If you want full rows then you can use not exists :
select t.*
from table t
where not exists (select 1
from table t1
where t1.name = t.name and (t1.score < 9 or t1.score is null)
);
You seem to be treated NULL scores as a value less than 9. You can also just use coalesce() with min():
select name
from have
group by name
having min(coalesce(score, 0)) >= 9;
Note that select distinct is almost never useful with group by -- and SAS proc sql probably does not optimize it well.

Filter data based on multiple rows SQL

This is probably as simple SQL query. I'm finding it little tricky, as it's been a while I've written SQL.
ID NAME VALUE
--- ------ -------
1 Country Brazil
1 Country India
2 Country US
2 EmpLevel 1
3 EmpLevel 3
Pseudo Query:
Select *
from table_name
where (country = US or country = Brazil)
and (Employee_level = 1 or Employee_level = 3)
This query should return
ID NAME VALUE
--- ------ -------
2 Country US
2 EmpLevel 1
(As record with ID - 2 has Country as 'US' and EmpLevel '1')
I went through couple SO posts as well.
Multiple row SQL Where clause
SQL subselect filtering based on multiple sub-rows
Evaluation of multiples 'IN' Expressions in 'WHERE' clauses in mysql
I assume you're expected results for the country should be US instead of Brazil. Here's one option using a join with conditional aggregation:
select y.*
from yourtable y join (
select id
from yourtable
group by id
having max(case when name = 'Country' then value end) in ('US','Brazil') and
max(case when name = 'EmpLevel' then value end) in ('1','3')
) y2 on y.id = y2.id
SQL Fiddle Demo

Counting values in columns

What I am looking for is to group by and count the total of different data in the same table and have them show in two different columns. Like below.
Data in table A
Fields:
Name Type
Bob 1
John 2
Bob 1
Steve 1
John 1
Bob 2
Desired result from query:
Name Type 1 Type 2
Bob 2 1
John 1 1
Steve 1 0
This will do the trick in SQL Server:
SELECT
name,
SUM( CASE type WHEN 1 THEN 1 ELSE 0 END) AS type1,
SUM( CASE type WHEN 2 THEN 1 ELSE 0 END) AS type2
FROM
myTable
GROUP BY
name
No time to write the code, but the Case statement is what you want here. SImply havea value of 1 if it meets the case and zero if it deosn't. Then you can sum the columns.
Use two separate GROUP BY subqueries.
SELECT Name, a.Count1, b.Count2
from myTable
JOIN
(SELECT Name, SUM(Type) AS Count1 FROM myTable GROUP BY Name WHERE Type=1) AS a ON a.Name = myTable.Name
(SELECT Name, SUM(Type) FROM myTable GROUP BY Name WHERE Type=2) AS b ON b.Name = myTable.Name
You're looking for a CrossTab solution. The above solutions will work, but you'll come unstuck if you want a general solution and have N types.
A CrossTab solution will solve this for you. If this is for quickly crunching some numbers then dump your data into Excel and use the native Pivot Table feature.
If it's for a RDBMS in an app, then it depends upon the RDBMS. MS SQL 2005 and above has a crosstab syntax. See:
http://www.databasejournal.com/features/mssql/article.php/3521101/Cross-Tab-reports-in-SQL-Server-2005.htm
#Seb has a good solution, but it's server-dependent. Here's an alternate using subselects that should be portable:
select
name,
(select count(type) from myTable where type=1 and name=a.name) as type1,
(select count(type) from myTable where type=2 and name=a.name) as type2
from
myTable as a
group by
name