Left outer join not showing second table as null - mysql

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

Related

Mysql insert a row only if id exist in another table

I have 2 simple table
table1 -> p_id | s_id
table2 -> p_id | s_id
The two table are same. The p_id ai value.
I would like to insert into the table2 a row, but **only if p_id is exist in table1. This is possible? (MySQL)
INSERT INTO table1 (p_id, s_id)
SELECT * FROM (SELECT '100', '2') AS tmp
WHERE NOT EXISTS (SELECT p_id FROM table2 WHERE p_id = '100')
LIMIT 1
You can insert into a table based on any SELECT query. For example:
INSERT INTO table2 (p_id, s_id)
SELECT p_id, 2 FROM table1 WHERE p_id = 100;
If there are zero rows in table1 with the specified p_id value, this is a no-op. That is, it inserts zero rows into table2. If there is 1 row in table1 with that p_id value, it inserts into table2.
No need for LIMIT 1 because if p_id is the primary key then there is guaranteed to be only 1 or 0 rows with the given value.
Try This
Insert into table2 (p_id,s_id) Select p_id,'2' as s_id FROM table1 where p_id=100 LIMIT 1

how to get the desired output in sql server 2008

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

Want one non-duplicated record insertion but sql inserts multiple records

My table has these columns:
int ID (Is Identity)
BusinessFilterPhrase nvarchar(50)
BusinessCategoryID int
Want to insert one record 'been' and 4 only if there not exists a record with 'been'. The statement below insert multiple records depend on how many record that do not have 'been'. So if my table have no record with data 'been' and there are 3 records in the table, it will insert 3 records with the new data 'been' and 4. I'm confused.
insert into tblBusinessName(BusinessFilterPhrase, BusinessCategoryID)
select 'been', 4
from tblBusinessName t1
where NOT EXISTS (select 1
from tblBusinessName d1
where d1.BusinessFilterPhrase = 'been'
)
It seem inserting top 1 into the first select work. Any other way to do this without making BuisnessFilterPhrase Unique in the table?
insert into tblBusinessName(BusinessFilterPhrase, BusinessCategoryID)
select top 1 'been', 4
from tblBusinessName t1
where NOT EXISTS (select 1
from tblBusinessName d1
where d1.BusinessFilterPhrase = 'been'
)
Just found out this statement will not insert anything if your table is blank. Note select top 1.
Just don't select from the table at all:
insert into tblBusinessName(BusinessFilterPhrase, BusinessCategoryID)
select 'been', 4
where not exists (select * from tblBusinessName where BusinessFilterPhrase = 'been')
Or alternatively:
if not exists (select * from tblBusinessName where BusinessFilterPhrase = 'been')
begin
insert into tblBusinessName(BusinessFilterPhrase, BusinessCategoryID)
select 'been', 4
end

complex sql update

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 ))

Delete rows without leading zeros

I have a table with a column (registration_no varchar(9)). Here is a sample:
id registration no
1 42400065
2 483877668
3 019000702
4 837478848
5 464657588
6 19000702
7 042400065
Please take note of registration numbers like (042400065) and (42400065), they are almost the same, the difference is just the leading zero.
I want to select all registration numbers that have the same case as above and delete the ones without a leading zero i.e (42400065)
pls, also note that before i delete the ones without leading zeros (42400065), i need to be sure that there is an equivalent with leading zeros(042400065)
declare #T table
(
id int,
[registration no] varchar(9)
)
insert into #T values
(1, '42400065'),
(2, '483877668'),
(3, '019000702'),
(4, '837478848'),
(5, '464657588'),
(6, '19000702'),
(7, '042400065')
;with C as
(
select row_number() over(partition by cast([registration no] as int)
order by [registration no]) as rn
from #T
)
delete from C
where rn > 1
create table temp id int;
insert into temp select id from your_table a where left (registration_no, ) = '0' and
exists select id from your_table
where a.registration_no = concat ('0', registration_no)
delete from your_table where id in (select id from temp);
drop table temp;
I think you can do this with a single DELETE statement. The JOIN ensures that only duplicates can get deleted, and the constraint limits it further by the registration numbers that don't start with a '0'.
DELETE
r1
FROM
Registration r1
JOIN
Registration r2 ON RIGHT(r1.RegistrationNumber, 8) = r2.RegistrationNumber
WHERE
LEFT(r1.RegistrationNumber, 1) <> '0'
Your table looks like this after running the above DELETE. I tested it on a SQL Server 2008 instance.
ID RegistrationNumber
----------- ------------------
2 483877668
3 019000702
4 837478848
5 464657588
7 042400065
This solution won't depend on the registration numbers being a particular length, it just looks for the ones that are the same integer, yet not the same value (because of the leading zeroes) and selects for the entry that has a '0' as the first character.
DELETE r
FROM Registration AS r
JOIN Registration AS r1 ON r.RegistrationNo = CAST(r1.RegistrationNo AS INT)
AND r.RegistrationNo <> r1.RegistrationNo
WHERE CHARINDEX('0',r.registrationno) = 1