How to insert a table conditionally - sql-server-2008

I have a table tbl1(col1, col2, col3, ..., coln), col1 and col2 together are the primary keys. I am trying to insert records from a temporary table #t to tbl1 using following query
insert into tbl1(col1, col2, col3, ..., colm)
select #t.col1, #t.col2, #t.col3, ..., #t.colm
from #t where col2 <> #t.col2
However, I got following error , The multi-part identifier "tblDailyBalanceHistory.BalanceDate" could not be bound. How do I fix my query?

I think your problem is with your WHERE criteria. You can't say col2 <> #t.col2 because col2 hasn't been defined.
Try something like this:
insert into tbl1(col1, col2, col3, ..., colm)
select #t.col1, #t.col2, #t.col3, ..., #t.colm
from #t
left join tbl1 on #t.col2 = tbl1.col2
where tbl1.col2 is null
Good luck.

Related

MYSQL: Insert one value from another table while populating other columns regularly

Lets say we have a table (1):
id | col1 | col2
And another table (2):
id | col3
Task is to insert all col3 distinct values to col1 at the same time populating col2 with random integer value
A couple of solutions here.
This uses a sub query to return the distinct values of col2.
INSERT INTO table1 (id, col1, col2)
SELECT NULL, col2, FLOOR(RAND()*(1000))+1
FROM
(
SELECT DISTINCT col2
FROM table2
)
The following abuses the GROUP BY clause to only generate rows for distinct values of col2. While this should be OK on a default install of MySQL, it might not work depending on the options set up for your installation and also probably wouldn't work in other flavours of SQL.
INSERT INTO table1 (id, col1, col2)
SELECT NULL, col2, FLOOR(RAND()*(1000))+1
FROM table2
GROUP BY col2

Add "on duplicate key update" clause to insert into query

I'm starting with a query like this:
insert into summary ( col1, col2, Total )
select col1, col2, count(col4) as total from importdata
where col1 = 'abc' and col4 in ('1A', '2A')
group by col1, col2
order by col1, col2
and I haven't been able to determine how the correct 'on duplicate' clause. The clause I think I need is
on duplicate key update total=count(col4)
and I've placed it as the very last line in the query and as the line after the where clause, but both generated errors. Is my clause even correct and where does it need to go?
(Worst case I can use 'insert ignore', but I think doing the update would be better.)
You can't use COUNT or other group functions in the ON DUPLICATE KEY UPDATE clause. What you can do instead is this:
INSERT INTO summary ( col1, col2, Total )
SELECT col1, col2, count(col4)
FROM importdata
WHERE col1 = 'abc' AND col4 IN ('1A', '2A')
GROUP BY col1, col2
ORDER BY col1, col2
ON DUPLICATE KEY UPDATE Total = VALUES(Total)
This says, if there is a duplicate key, instead of inserting a new row just set the column total to the value you would have inserted in Total. Note that I got rid of the as total -- that would have caused problems as you already have a column named Total, and the names are case-insensitive.
You cannot use functions for the duplicate key update, however, you could create a variable and then use that variable.
INSERT INTO summary (col1, col2, Total)
select col1, col2, #totalCount := count(col4) as Total from importdata
where col1 = 'abc' and col4 in ('1A', '2A')
group by col1, col2
order by col1, col2
) ON DUPLICATE KEY UPDATE Total = #totalCount;

ON DUPLICATE KEY UPDATE - help needed

My problem is i have an insert that updates the query on duplicate key and it is like the one below:
INSERT INTO TABLE
(COL1, COL2, COL3 , ETC...)
SELECT
COLA1, COLA2, COUNT(1) , ETC...
FROM TABLE2
WHERE 'CONDITION'
GROUP BY COL1, COL2, COL3
ON DUPLICATE KEY UPDATE COL1=VALUES(COLA1), COL3=COUNT(1)
THIS QUERY RETURNS AN ERROR: General error: 1111 Invalid use of group function SQL
COL1, COD2, COL3 ARE COMPLEX KEY.
Try this:
INSERT INTO TABLE(COL1, COL2, COL3, ETC...)
SELECT COLA1, COLA2, COUNT(1), ETC...
FROM TABLE2
WHERE 'CONDITION'
GROUP BY COL1, COL2, COL3
ON DUPLICATE KEY UPDATE COL1 = VALUES(COL1), COL3 = VALUES(COL3);
That is, refer to the names in the values1 statement, not the expressions in the select statement.

Similar WHERE clause in a long UNION statement in SQL Server 2008 R2

In a stored procedure, I need to INSERT the result of a long UNION into a temp table.
The WHERE clause is the same for all tables, which is being in a SELECT DISTINCT.
Simplified for readability, it goes like this:
INSERT INTO #MyTemp
SELECT col1, col2, col3 FROM tab1 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
SELECT col1, col2, col3 FROM tab2 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
SELECT col1, col2, col3 FROM tab3 WHERE col1 in (SELECT DISTINCT myId FROM TabIds) UNION
.
.
.
SELECT col1, col2, col3 FROM tab20 WHERE col1 in (SELECT DISTINCT myId FROM TabIds)
Although TabIds is a small temp table, typically 3-6 records long, this seems to be pretty inneficient.
Is there a better way to do this?
Summarizing my question:
Is there a way I can do SELECT DISTINCT myId FROM TabIds just once and assign it to a kind of array/list/set (not to another temp table) and just use that in the WHERE clauses, and if there is a way, does it really matter for such a small (3-6 recs) temp table?
I'm ignoring your requirement ("not to another temp table") because I don't believe it is well-founded. Try and see if this solution gives you better performance:
SELECT i = myId
INTO #x
FROM dbo.TabIds -- please always use schema prefix
GROUP BY myId;
CREATE UNIQUE CLUSTERED INDEX x ON #x(i);
INSERT INTO #MyTemp(col1, col2, col3)
SELECT col1, col2, col3
FROM
(
SELECT col1, col2, col3 FROM dbo.tab1 WHERE EXISTS -- likely better than IN
(SELECT 1 FROM #x WHERE i = tab1.col1)
UNION ALL
SELECT col1, col2, col3 FROM dbo.tab2 WHERE EXISTS
(SELECT 1 FROM #x WHERE i = tab2.col1)
UNION ALL
...
UNION ALL
SELECT col1, col2, col3 FROM dbo.tab20 WHERE EXISTS
(SELECT 1 FROM #x WHERE i = tab20.col1)
) AS x
GROUP BY col1, col2, col3; -- likely more efficient than `UNION` to remove dupes
Of course this will work best if col1 is indexed in all 20 tables, and if that index includes col2 and col3.
The reason I suggested a view is not because I thought it would make this code run faster. Just that you could create a view that generates this UNION for you, making this code simpler (and any other code that repeats this monotonous UNION). It was a suggestion for convenience, not for performance - though I need to make it clear that using a view does not magically make things slower. Sometimes I can, but that's a dangerous and illogical reason to avoid views.
Finally, I'd strongly consider normalization. Why are these 20 different tables in the first place, when they could all be in one single table?
CREATE TABLE dbo.Normal
(
SourceTableID INT,
col1 <data type>,
col2 <data type>,
col3 <data type>
);
-- indexes / constraints
INSERT dbo.Normal
SELECT 1, col1, col2, col3 FROM dbo.tab1
UNION ALL
SELECT 2, col1, col2, col3 FROM dbo.tab2
UNION ALL
...
UNION ALL
SELECT 20, col1, col2, col3 FROM dbo.tab20;
Now all your queries can simply reference this new table. If you will commonly look for only one of the sources (e.g. tab5), then indexing or partitioning on SourceTableID would be useful.
What you're doing, conceptually, is fine for one-offs and data loads. I hope this isn't part of a bigger pattern in production code, though.
What you're looking for is a Common Table Expression.
My T-SQL is a bit rusty, but with a CTE, your query would go something like:
WITH TabIds_CTE AS (SELECT DISTINCT myId FROM TabIds)
INSERT INTO #MyTemp
SELECT col1, col2, col3 FROM tab1 WHERE col1 IN (SELECT * FROM TabIds_CTE)
UNION ALL ...
I think the following might be better for small tables, but still - it's horrible idea to leave it like this in some production process :)
INSERT INTO #MyTemp (col1,col2,col3)
select distinct
x.col1,x.col2,x.col3
from (
SELECT col1, col2, col3 FROM tab1 union all
SELECT col1, col2, col3 FROM tab2 union all
SELECT col1, col2, col3 FROM tab3 union all
-- ...
SELECT col1, col2, col3 FROM tab20
) x
join (
SELECT DISTINCT myId FROM TabIds
) y
on x.col1=y.myid

Selecting distinct 2 columns combination in mysql

I have a mysql table that looks like this:
1 value1 value2 3534
2 value1 value1 8456
3 value1 value2 3566
4 value1 value3 7345
5 value2 value3 6734
I need a query to select all the rows with distinct column 2 and 3, for example the output I want for this example will look like this:
1 value1 value2 3534
2 value1 value1 8456
4 value1 value3 7345
5 value2 value3 6734
i've found a few samples on how to do it but they all select distinct on each column individually.
Update 1
Better you use this against above.
SELECT id, col2, col3, col4
FROM yourtable
GROUP BY col2, col3;
Demo
The reason I am saying is because using CONCAT, I am not getting desired result in this case. First query is returning me 5 rows however CONCAT is returning me 4 rows which is INCORRECT.
Hope you got my point.
Assumed the columns in the table are (id, col2, col3, col4).
SELECT DISTINCT(CONCAT(col2, col3)) as "dummy column", id, col2, col3, col4
FROM yourtable
GROUP BY CONCAT(col2, col3);
OR
SELECT id, col2, col3, MIN(col4)
FROM yourtable
GROUP BY col2, col3;
live working example
Assuming that the first column is unique, you can do this:
SELECT id, col2, col3, col4
FROM yourtable
WHERE id IN
(
SELECT MIN(id)
FROM yourtable
GROUP BY col2, col3
)
See it working online: sqlfiddle
Assuming the columns in the table are (id, col1, col2, col3), you could:
SELECT *
FROM YourTable yt
JOIN (
SELECT MIN(id) as minid
FROM YourTable
GROUP BY
col1, col2
) filter
ON filter.minid = yt.id
This query makes sure that the combination of column1 and column2 is unique, while selecting the minimum value of column three
SELECT col1, col2, MIN(col3)
FROM yourTable
GROUP BY col1, col2
THe simplest query for this is
SELECT col1, col2, MIN(col3)
FROM myTable
GROUP BY col1, col2
Using the group by method is returning me extra rows, where as explicitly checking each field although longer returns the same no of records as count(Distinct ..)
SELECT id, col2, col3, col4
FROM yourtable yt
WHERE id =
(
SELECT MIN(id)
FROM yourtable yt1
WHERE yt.col2 = yt1.col2
AND yt.col3 = yt1.col3
)