Table Structure
EID COLA COLB
1 name A
1 age 23
1 city hyd
1 email abc#live.in
1 mobile 45126
2 name B
2 age 43
2 city bang
3 name C
3 age 13
3 city bang
3 email jdf#live.in
I would like to have the output as below
ID||COLA||COLB
1||name||A
1||age||23
1||city||hyd
1||email||abc#live.in
1||mobile||45126
2||name||B
2||age||43
2||city||bang
2||email||NULL
2||mobile||NULL
3||name||C
3||age||13
3||city||bang
3||email||jdf#live.in
3||mobile||NULL
Can you kindly let me know how to achieve this output.
how to display the result where any of the mandatory fields (name,age,city,email,mobile)are missing then it should display as that field as Null, in the query we would provide in the where clause by filtering a single id value and cola as (name,age,city,email,mobile)
my Query:
select
case colA
when cola then colA+'||'+colB
end
from tbl
where cola in ('name','age','city','email','mobile')
Let me start by saying that what you are asking would have been really easy if your table structure had required columns like name, age, city etc. Name Value Pair is not a good design for such tables, not to mention serious performance issues which will plague any solution against this structure.
Having said that, you can use either PIVOT / UNPIVOT or an Attribute table (a table containing list of attribute required) and GROUP BY with CROSS JOIN.
Sample Data
DECLARE #table1 TABLE(
EID INT, COLA VARCHAR(30), COLB VARCHAR(30) )
INSERT INTO #table1 VALUES
(1,'name','A'),
(1,'age','23'),
(1,'city','hyd'),
(1,'email','abc#live.in'),
(1,'mobile','45126'),
(2,'name','B'),
(2,'age','43'),
(2,'city','bang'),
(3,'name','C'),
(3,'age','13'),
(3,'city','bang'),
(3,'email','jdf#live.in');
Query using PIVOT / UNPIVOT
SELECT EID, COLA,NULLIF(COLB,'') COLB
FROM
(
SELECT EID,ISNULL([name],'') name,ISNULL([age],'') [age],ISNULL([city],'') [city],ISNULL([email],'') [email],ISNULL([mobile],'') [mobile]
FROM (SELECT EID,COLA,COLB
FROM #table1) T
PIVOT ( MAX(COLB) FOR COLA IN ( [name],[age],[city],[email],[mobile] ) ) AS pvt
) tbl
UNPIVOT (COLB FOR ColA IN (name,age,city,email,mobile)) AS Upvt
Notice that I am using ISNULL(col,'') because UNPIVOT excludes NULL values. If '' is a valid value for you, you can use another string to denote NULL or use the GROUP BY solution.
Query using Attribute table and GROUP BY with CROSS JOIN
;WITH Cols(Name) AS
(
SELECT 'name' UNION ALL SELECT 'age' UNION ALL SELECT 'city' UNION ALL SELECT 'email' UNION ALL SELECT 'mobile'
)
SELECT t.EID,C.Name,t1.COLB
FROM
(
SELECT EID
FROM #table1
GROUP BY EID
) t
CROSS JOIN Cols c
LEFT JOIN #table1 t1 ON t1.EID = t.EID and t1.COLA = C.Name
CREATE TABLE DesireOutput(EID nvarchar(10),COLA NVARCHAR(10),COLB nvarchar(50))
INSERT INTO DesireOutput VALUES ('1','name','A' )
INSERT INTO DesireOutput VALUES ('1','age','23')
INSERT INTO DesireOutput VALUES ('1','city','hyd')
INSERT INTO DesireOutput VALUES ('1','email','abc#live.IN')
INSERT INTO DesireOutput VALUES ('1','mobile','45126')
INSERT INTO DesireOutput VALUES ('2','name','B')
INSERT INTO DesireOutput VALUES ('2','age','43')
INSERT INTO DesireOutput VALUES ('2','city','bang')
INSERT INTO DesireOutput VALUES ('3','name','C')
INSERT INTO DesireOutput VALUES ('3','age','13')
INSERT INTO DesireOutput VALUES ('3','city','bang')
INSERT INTO DesireOutput VALUES ('3','email','jdf#live.IN')
DECLARE #t AS TABLE ( ColA NVARCHAR(50) )
INSERT INTO #t
SELECT DISTINCT
D.COLA
FROM DesireOutput D
SELECT t.EID , c.ColA , t1.COLB FROM ( SELECT
EID FROM DesireOutput GROUP BY EID
) t
CROSS JOIN #t c
LEFT JOIN DesireOutput t1 ON t1.EID = t.EID
AND t1.COLA = c.ColA ORDER BY EID
Related
I have a table of Friends (Ann, Bob, Carl) and a table of Fruits (Apple, Banana, Cherry, Date, Fig, Grapefruit)
I need to create an intersection table (Friends X Fruit) that associates each Friend with 3 randomly selected fruits.
For example:
Ann might be associated with Cherry, Date, Fig
Bob might be associated with Apple, Fig, Banana
Carl might be associated with Banana, Cherry, Date
I have developed a script that works well for only ONE friend (pasted below), but I am struggling to expand the script to handle all of the friends at once.
(If I remove the WHERE clause, then every friend gets assigned the same set of fruits, which doesn't meet my requirement).
Setup statements and current script pasted below.
Thank you for any guidance!
CREATE TABLE TempFriends ( FirstName VARCHAR(24) );
CREATE TABLE TempFruits ( FruitName VARCHAR(24) );
CREATE TABLE FriendsAndFruits( FirstName VARCHAR(24), FruitName VARCHAR(24) );
INSERT INTO TempFriends VALUES ('Ann'), ('Bob'), ('Carl');
INSERT INTO TempFruits VALUES ('Apple'), ('Banana'), ('Cherry'), ('Date'), ('Fig'), ('Grapefruit');
INSERT INTO FriendsAndFruits( FirstName, FruitName )
SELECT FirstName, FruitName
FROM TempFriends
INNER JOIN ( SELECT FruitName FROM TempFruits ORDER BY RAND() LIMIT 3 ) RandomFruit
WHERE FirstName = 'Bob';
INSERT INTO FriendsAndFruits
SELECT FirstName,
FruitName
FROM (
SELECT FirstName,
FruitName,
ROW_NUMBER() OVER (PARTITION BY FirstName ORDER BY RAND()) rn
FROM TempFriends
CROSS JOIN TempFruits
) subquery
WHERE rn <= 3;
INSERT INTO FriendsAndFruits( FirstName, FruitName )
SELECT FirstName, FruitName
FROM TempFriends
JOIN LATERAL (
SELECT FruitName
FROM TempFruits
ORDER BY TempFriends.FirstName, RAND() LIMIT 3
) RandomFruit;
INSERT INTO FriendsAndFruits( FirstName, FruitName )
SELECT FirstName, FruitName
FROM TempFriends
JOIN LATERAL (
SELECT TempFriends.FirstName tmp, FruitName
FROM TempFruits
ORDER BY RAND() LIMIT 3
) RandomFruit;
fiddle
Data
Brcode name
1. A
2. A
3. A
Expected result
Brcode Name Common
1 A 1,2,3
2 A 1,2,3
3 A 1,2,3
Yes you can do a join.
CREATE TABLE test_tbl (
Brcode int(9),
name varchar(3) );
INSERT INTO test_tbl VALUES (1,'A'),
(2,'A'),
(3,'A');
SELECT t1.Brcode,
t1.name,
t2.common
FROM test_tbl t1
inner join
(
select name ,group_concat(Brcode SEPARATOR ',') as Common from test_tbl group by name
) as t2 on t1.name=t2.name;
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/99
Result:
Table structre
table 1
account
123
1234
12345
123456
table 2
account
123
1234
12345
I want to return table a record 123456 on account for table1 and null for column 2 when it doesnt match table 2
SQL
SELECT table1.account, table2.account
from table1
left outer join table2
on (table1.account= table2.account)
Your where statement explicitly asked for non-null rows with table2.dates = '19-jul-17'
You should modify your query to check for nulls:
SELECT
table1.account, table2.account
from table1
left outer join table2
on (table1.account= table2.account)
where
t1.dates='20170719'
and ( table2.account is NULL
or
table2.dates = '20170719'
)
This matches rows that have a specific date in the first table, and either null or a specific date on the second.
Note the date literal. The original query used a locale-specific format. This can fail easily faile in locales that don't use that format. Never mind the two digit year.
YYYYMMDD on the other hand is unambiguous.
UPDATE
Once the where clause is removed, NULLs are returned as expected :
declare #table1 table (id int)
declare #table2 table (id int)
insert into #table1
values
(123 ),
(1234 ),
(12345 ),
(123456)
insert into #table2
values
(123 ),
(1234 ),
(12345)
SELECT t1.id, t2.id
from #table1 t1
left outer join #table2 t2
on (t1.id= t2.id)
Returns
id id
123 123
1234 1234
12345 12345
123456 NULL
If the question is "how do I get the non-matching row" the answer is use WHERE tabl2.ID IS NULL
Everything is OK in your query, If you are using any where clause, please remove and check, BTW i am not able to reproduce your issue. PFB attempt, The query gives expected result
create table #tmp1( ID int)
create table #tmp2( ID int)
Insert into #tmp1 values('123')
Insert into #tmp1 values ('1234')
Insert into #tmp1 values ('12345')
Insert into #tmp1 values ('123456')
Insert into #tmp2 values('123')
Insert into #tmp2 values ('1234')
Insert into #tmp2 values ('12345')
select * from #tmp1
select * from #tmp2
SELECT #tmp1.ID, #tmp2.ID from #tmp1 left outer join #tmp2 on (#tmp1.ID=#tmp2.ID)
drop table #tmp1
drop table #tmp2
The result is:
ID ID
123 123
1234 1234
12345 12345
123456 NULL
I have a table that contains two columns
ID | Name
----------------
1 | John
2 | Sam
3 | Peter
6 | Mike
It has missed IDs. In this case these are 4 and 5.
How do I find and insert them together with random names into this table?
Update: cursors and temp tables are not allowed. The random name should be 'Name_'+ some random number. Maybe it would be the specified value like 'Abby'. So it doesn't matter.
Using a recursive CTE you can determine the missing IDs as follows
DECLARE #Table TABLE(
ID INT,
Name VARCHAR(10)
)
INSERT INTO #Table VALUES (1, 'John'),(2, 'Sam'),(3,'Peter'),(6, 'Mike')
DECLARE #StartID INT,
#EndID INT
SELECT #StartID = MIN(ID),
#EndID = MAX(ID)
FROM #Table
;WITH IDS AS (
SELECT #StartID IDEntry
UNION ALL
SELECT IDEntry + 1
FROM IDS
WHERE IDEntry + 1 <= #EndID
)
SELECT IDS.IDEntry [ID]
FROM IDS LEFT JOIN
#Table t ON IDS.IDEntry = t.ID
WHERE t.ID IS NULL
OPTION (MAXRECURSION 0)
The option MAXRECURSION 0 will allow the code to avoid the recursion limit of SQL SERVER
From Query Hints and WITH common_table_expression (Transact-SQL)
MAXRECURSION number Specifies the maximum number of recursions
allowed for this query. number is a nonnegative integer between 0 and
32767. When 0 is specified, no limit is applied. If this option is not specified, the default limit for the server is 100.
When the specified or default number for MAXRECURSION limit is reached
during query execution, the query is ended and an error is returned.
Because of this error, all effects of the statement are rolled back.
If the statement is a SELECT statement, partial results or no results
may be returned. Any partial results returned may not include all rows
on recursion levels beyond the specified maximum recursion level.
Generating the RANDOM names will largly be affected by the requirements of such a name, and the column type of such a name. What exactly does this random name entail?
You can do this using a recursive Common Table Expression CTE. Here's an example how:
DECLARE #MaxId INT
SELECT #MaxId = MAX(ID) from MyTable
;WITH Numbers(Number) AS
(
SELECT 1
UNION ALL
SELECT Number + 1 FROM Numbers WHERE Number < #MaxId
)
SELECT n.Number, 'Random Name'
FROM Numbers n
LEFT OUTER JOIN MyTable t ON n.Number=t.ID
WHERE t.ID IS NULL
Here are a couple of articles about CTEs that will be helpful to Using Common Table Expressions and Recursive Queries Using Common Table Expressions
Start by selecting the highest number in the table (select top 1 id desc), or select max(id), then run a while loop to iterate from 1...max.
See this article about looping.
For each iteration, see if the row exists, and if not, insert into table, with that ID.
I think recursive CTE is a better solution, because it's going to be faster, but here is what worked for me:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestTable]') AND type in (N'U'))
DROP TABLE [dbo].[TestTable]
GO
CREATE TABLE [dbo].[TestTable](
[Id] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
))
GO
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (1, 'John')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (2, 'Sam')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (3, 'Peter')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (6, 'Mike')
GO
declare #mod int
select #mod = MAX(number)+1 from master..spt_values where [type] = 'P'
INSERT INTO [dbo].[TestTable]
SELECT y.Id,'Name_' + cast(newid() as varchar(45)) Name from
(
SELECT TOP (select MAX(Id) from [dbo].[TestTable]) x.Id from
(
SELECT
t1.number*#mod + t2.number Id
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
WHERE t1.[type] = 'P' and t2.[type] = 'P'
) x
WHERE x.Id > 0
ORDER BY x.Id
) y
LEFT JOIN [dbo].[TestTable] on [TestTable].Id = y.Id
where [TestTable].Id IS NULL
GO
select * from [dbo].[TestTable]
order by Id
GO
http://www.sqlfiddle.com/#!3/46c7b/18
It's actually very simple :
Create a table called #All_numbers which should contain all the natural number in the range that you are looking for.
#list is a table containing your data
select a.num as missing_number ,
'Random_Name' + convert(varchar, a.num)
from #All_numbers a left outer join #list l on a.num = l.Id
where l.id is null
The table MyTable contains 4 columns.
id, phone columns are unique.
id, phone, zipcode are never empty.
id - phone - salary - zipcode
1 - 61730459987 - $56052.45 - 02456
2 - 21249620709 - NULL - 10023
3 - 21200830859 - $39089.28 - 10023
...
10000 - 64600830857 - $46063.72 - 03795**
I need to remove NULLs by replacing them with salary_estimates, based on information from the same zip-codes.
As for the example above, NULL at row #2 could be replaced with $39089.28 (we can find from the table that another person with the same zip-code 10023 earns $39089.28, so it's OK to update NULL for #2 with $39089.28).
So, after we run this query, the number of empty cells could be reduced (although not up to zero).
Could anybody suggest an update query for this problem?
UPDATE
MyTable AS tu
JOIN
( SELECT zipcode
, AVG(salary) AS SalaryEstimate --- AVG, MAX, MIN
--- your choice
FROM MyTable
WHERE salary IS NOT NULL
GROUP BY zipcode
) AS te
ON te.zipcode = tu.zipcode
SET
tu.salary = te.SalaryEstimate
WHERE
tu.salary IS NULL
I am not sure it will work for mysql. But in MSSQL you can do like this :
UPDATE MyTable
SET salary = (select top 1 salary from MyTable where zipcode = t1.zipcode and salary is not null)
FROM MyTable t1
WHERE t1.salary is null
You need to check equivalent join case for mysql.
Ref. Test Query :
create table #temp (id int, salary decimal(18,2), zipcode varchar(10))
insert into #temp values (1,56052.45,02456)
insert into #temp values (2,NULL,1023)
insert into #temp values (3,39089.28,1023)
insert into #temp values (4,46063.72,03795)
insert into #temp values (5,NULL,02456)
UPDATE #temp
SET salary = (select top 1 salary from #temp where zipcode = t1.zipcode and salary is not null)
FROM #temp t1
WHERE t1.salary is null
select * from #temp
drop table #temp
You can do like this: if salary is null it will replace with salary of that zipcode.
isnull(salary,(Select top 1 salary from MyTable where zipcode=10023 ))