Fill in the missing integers in table using SQL - sql

I have a table as :
I want to insert the missing digits like 2,4,5 and make the corresponding values to be 0.
Like this:
I don't want to use loops(as my SQL version doesn't support it). Is there any way this can be attained in SQL?

I Never work with postgresql. But the logic should be something like below.
CREATE TEMPORARY TABLE temp_data
(
Month int,
amount bigint
)
insert into temp_location
select 1,0 union
select 2,0 union
select 3,0 union
select 4,0 union
select 5,0 union
select 6,0 union
select 7,0 union
select 8,0 union
select 9,0 union
select 10,0 union
select 11,0 union
selecct 12,0
You can Insert only records which is missing in your table using left Join
insert into yourtable
select td.Months,td.Amount
from temp_data td
left join yourtable yt on td.Months = yt.months
where yt.months is null

Related

SQL Get First Non Null Value By Date From A Table

Im trying a CASE expression, something like this:
LEFT OUTER JOIN table_1 AS T1
ON T2.common_id = T1.common_id
CASE WHEN T1.column_1 IS NOT NULL
THEN T1.column_1
WHEN T1.column_1 IS NULL
THEN get first value from T1.column that is not null by date
ELSE 0
END
Its the logic for that 6th line which I have written out what I want that I can't quite get right.
THEN get first value from T1.column that is not null by date
I have been looking at the FIRST_VALUE function but can't quite figure it out correctly. But there are maybe other ways to get it to work.
you can to find FIRST_VALUE that is not null with use this query
First use order by date for find date is null
after get value FIRST_VALUE date with FIRST_VALUE
select *,FIRST_VALUE(date) over(partition by T1.common_id order by case when date is not null then 1 else 2 end)
from #table_2 T2
LEFT OUTER JOIN #table_1 AS T1
ON T2.common_id = T1.common_id
You can to insert the basic data with the following codes
create table #table_1 (id int,common_id int,date datetime)
create table #table_2 (id int,common_id int,name varchar(100))
insert into #table_1(id,common_id,date)
select 1,1,'2015-05-24' union select 2,1, null union select 3,1, '2014-09-01' union
select 4,4,null union select 5,4, '2019-08-05' union select 6,4, '2000-09-07' union
select 7,7,null union select 8,7, '2019-08-05' union
select 9,12,'2019-08-06' union select 10,12, '2019-08-05' union
select 11,18,'2019-08-06' union select 12,19, '2019-08-05'
insert into #table_2(id,common_id,name)
select 1,1,'a' union select 2,1, null union select 3,1, 'b' union
select 4,4,'k' union select 5,4, 't' union select 6,4, 'c' union
select 7,7,'aaa' union select 8,7, 'sada' union
select 9,12,'44dd' union select 9,12, '44'

Union All have mismatched column count

I am trying to union some table. But I am having some issues with the query as I have the following error:
Queries in UNION ALL have mismatched column count; query 1 has 10 columns, query 2 has 12 columns at [3:1]
The query used is:
SELECT * FROM `table_1`
UNION ALL
SELECT * ,null, FROM `table_2`
UNION ALL
SELECT * FROM `table_3`
UNION ALL
SELECT * FROM `table_4`
UNION ALL
SELECT * , null, FROM `table_5`
Please someone have any suggestions?
In a UNION ALL all queries need to be the same number of columns.
You need to post the schema of all tables. But according to the error message you posted, this could help for the 2 first tables:
SELECT *, null FROM `table_1` -- assuming table_1 has 10 columns, add 1 more empty to match the table_2
UNION ALL
SELECT * FROM `table_2` -- assuming table_2 has 11 columns
-- make the same to the rest of queries
-- UNION ALL
-- SELECT * FROM `table_3`
-- UNION ALL
-- SELECT * FROM `table_4`
-- UNION ALL
-- SELECT * , null, FROM `table_5`
Update:
Adding a example of union all declaring the columns:
SELECT
col1_str,
col2_str,
col3_int,
col4_int
FROM `table_1`
UNION ALL
SELECT
col2_str,
FORMAT_DATE("%Y-%m-%d", col1_date) as col1_str, -- transform a date column to string
col3_int,
null
FROM `table_2`

Perform a function after union of two tables

I have two tables that I want to union together then perform some math functions on the combined table.
I know how to do the math for each separate table, but throwing in a union table to go off of is out of my league.
Here's the math for one table using column header "UnitsReceived" and "AsnPsUnits"
The other table would have headers: "cUnitsReceived" and "cAsnPsUnits"
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from VenTest2
where ID<20
group by VendName
How would I perform this function after the union of two tables?
You'll need to get the unioned tables into some table object before performing your function. This could be done using:
A Common Table Expression
with cte as (
select ID, VALUE from A
union all
select ID, VALUE from B
)
select
*
,myfunction(VALUE) as MyFunctionResult
from
cte
A temp table
select ID, VALUE into #myTempTable from A
insert into #myTempTable select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTempTable
A table variable
declare #myTableVariable table (ID int, VALUE decimal)
insert into #myTableVariable
select ID, VALUE from A
union all
select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTableVariable
A sub query
select
*
,myfunction(VALUE) as MyFunctionResult
from
(
select ID, VALUE from A
union all
select ID, VALUE from B
) mySubQuery
This will help with the subq being the union
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from
(
select ID, UnitsReceived, AsnPsUnits from VenTest2 where ID<20
union
select ID1, UnitsReceived1, AsnPsUnits1 from VenTest1
)a
group by VendName
This is not the way, brothers:
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(10,2))) - (cast(sum(AsnPsUnits) as decimal(10,2)))) /(cast(sum(AsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from VenTest2
where ID<10
group by VendName
union
select cVendName,
1-abs(((cast(sum(cUnitsReceived) as decimal(10,2))) - (cast(sum(casnpsunits) as decimal(10,2)))) /(cast(sum(cAsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from CTest
where id <10
group by cvendname

SQL assigning incremental ID to subgroups

As the title says, I'm trying to add an extra column to a table which autoincrements everytime a different string in another column changes.
I would like to do this in a query.
Example:
MyCol GroupID
Cable 1
Cable 1
Foo 2
Foo 2
Foo 2
Fuzz 3
Fizz 4
Tv 5
Tv 5
The GroupID column is what I want to accomplish.
We can be sure that MyCol's strings will be the same in each subgroup (Foo will always be Foo, etc).
Thanks in advance
If I understand correctly, you can use dense_rank():
select t.*, dense_rank() over (order by col1) as groupid
from t;
You could make a temporal table with the distinct value of the MyCol and get the groupId throught the RowNumber of the temp table, and join the rownumbered result with your table.
This is a raw example in oracle:
WITH data AS
(SELECT 'Cable' MyCol FROM dual
UNION ALL
SELECT 'Cable' FROM dual
UNION ALL
SELECT 'Foo' FROM dual
UNION ALL
SELECT 'Foo' FROM dual
UNION ALL
SELECT 'Foo' FROM dual
UNION ALL
SELECT 'Fuzz' FROM dual
UNION ALL
SELECT 'Fizz' FROM dual
UNION ALL
SELECT 'Tv' FROM dual
UNION ALL
SELECT 'Tv' FROM dual
),
tablename AS
(SELECT * FROM data
),
temp AS
( SELECT DISTINCT mycol FROM tablename
),
temp2 AS
( SELECT mycol, rownum AS groupid from temp
)
SELECT tablename.mycol, temp2.groupid FROM temp2 JOIN tablename ON temp2.mycol = tablename.mycol
You could also check for a way to implement the tabibitosan method knowing that your column condition is string.

SQL Select Condition Question

I have a quick question about a select statement condition.
I have the following table with the following items. What I need to get is the object id that matches both type id's.
TypeId ObjectId
1 10
2 10
1 11
So I need to get both object 10 because it matches type id 1 and 2.
SELECT ObjectId
FROM Table
WHERE TypeId = 1
AND TypeId = 2
Obviously this doesn't work because it won't match both conditions for the same row. How do I perform this query?
Also note that I may pass in 2 or more type id's to narrow down the results.
Self-join:
SELECT t1.ObjectId
FROM Table AS t1
INNER JOIN Table AS t2
ON t1.ObjectId = t2.ObjectId
AND t1.TypeId = 1
AND t2.TypeId = 2
Note sure how you want the behavior to work when passing in values, but that's a start.
I upvoted the answer from #Cade Roux, and that's how I would do it.
But FWIW, here's an alternative solution:
SELECT ObjectId
FROM Table
WHERE TypeId IN (1, 2)
GROUP BY ObjectId
HAVING COUNT(*) = 2;
Assuming uniqueness over TypeId, ObjectId.
Re the comment from #Josh that he may need to search for three or more TypeId values:
The solution using JOIN requires a join per value you're searching for. The solution above using GROUP BY may be easier if you find yourself searching for an increasing number of values.
This code is written with Oracle in mind. It should be general enough for other flavors of SQL
select t1.ObjectId from Table t1
join Table t2 on t2.TypeId = 2 and t1.ObjectId = t2.ObjectId
where t1.TypeId = 1;
To add additional TypeIds, you just have to add another join:
select t1.ObjectId from Table t1
join Table t2 on t2.TypeId = 2 and t1.ObjectId = t2.ObjectId
join Table t3 on t3.TypeId = 3 and t1.ObjectId = t3.ObjectId
join Table t4 on t4.TypeId = 4 and t1.ObjectId = t4.ObjectId
where t1.TypeId = 1;
Important note: as you add more joins, performance will suffer a LOT.
In regards to Bill's answer you can change it to the following to get rid of the need to assume uniqueness:
SELECT ObjectId
FROM (SELECT distinct ObjectId, TypeId from Table)
WHERE TypeId IN (1, 2)
GROUP BY ObjectId
HAVING COUNT(*) = 2;
His way of doing it scales better as the number of types gets larger.
Try this
Sample Input:(Case 1)
declare #t table(Typeid int,ObjectId int)
insert into #t
select 1,10 union all select 2,10 union all
select 1,11
select * from #t
Sample Input:(Case 2)
declare #t table(Typeid int,ObjectId int)
insert into #t
select 1,10 union all select 2,10 union all
select 3,10 union all select 4,10 union all
select 5,10 union all select 6,10 union all
select 1,11 union all select 2,11 union all
select 3,11 union all select 4,11 union all
select 5,11 union all select 1,12 union all
select 2,12 union all select 3,12 union all
select 4,12 union all select 5,12 union all
select 6,12
select * from #t
Sample Input:(Case 3)[Duplicate entries are there]
declare #t table(Typeid int,ObjectId int)
insert into #t
select 1,10 union all select 2,10 union all
select 1,10 union all select 2,10 union all
select 3,10 union all select 4,10 union all
select 5,10 union all select 6,10 union all
select 1,11 union all select 2,11 union all
select 3,11 union all select 4,11 union all
select 5,11 union all select 1,12 union all
select 2,12 union all select 3,12 union all
select 4,12 union all select 5,12 union all
select 6,12 union all select 3,12
For case 1, the output should be 10
For case 2 & 3, the output should be 10 and 12
Query:
select X.ObjectId from
(
select
T.ObjectId
,count(ObjectId) cnt
from(select distinct ObjectId,Typeid from #t)T
where T.Typeid in(select Typeid from #t)
group by T.ObjectId )X
join (select max(Typeid) maxcnt from #t)Y
on X.cnt = Y.maxcnt