How do i avoid calling the same sql statement over and over - sql

I have a sql statement that says
SELECT coalesce((Select sum(SomeNumber)
FROM Table
WHERE ID NOT IN (SELECT IDs...)), 0) MyFirstNumber,
coalesce((Select sum(SomeNumber2)
FROM Table
WHERE ID NOT IN (SELECT IDs...)), 0) MySecondNumber
How can I make the (SELECT IDs...) query statement be called only once, say before the statement above.
I think it would be something like
DECLARE #MyIDs
SET #MyIDs = SELECT IDs FROM TABLE WHERE ...
SELECT coalesce((Select sum(SomeNumber)
FROM Table
WHERE ID NOT IN (#MyIDs)), 0) MyFirstNumber,
coalesce((Select sum(SomeNumber2)
FROM Table
WHERE ID NOT IN (#MyIDs)), 0) MySecondNumber

how about joining with that subselect and fitering only where the join is false ( returns null)
SELECT sum(coalesce(SomeNumber,0)) MyFirstNumber
,sum(coalesce(SomeNumber2,0)) MySecondNumber
FROM Table
LEFT JOIN (SELECT IDs.. FROM Table ) AS Filter ON Table.ID = Filter.ID
WHERE Filter.ID IS NULL

Calculate the amount in one SELECT statement
SELECT COALESCE(SUM(SomeNumber), 0) AS MyFirstNumber,
COALESCE(SUM(SomeNumber2), 0) AS MySecondNumber
FROM Table
WHERE ID NOT IN (SELECT IDs FROM TABLE WHERE...)
If need different conditions you can use CASE expression within SUM() functions
SELECT COALESCE(SUM(SomeNumber), 0) AS MyFirstNumber,
COALESCE(SUM(SomeNumber2), 0) AS MySecondNumber,
COALESCE(SUM(CASE WHEN ... THEN SomeNumber3 END), 0) AS MyThirdNumber
FROM Table
WHERE ID NOT IN (SELECT IDs FROM TABLE WHERE...)

Related

Insert or update data using cte_results in SQL Server

I have a query having cte with number of columns, I want to insert a record if ID from the results of that query does not exist in table that I am inserting, or if the ID exists I want to update data using that ID.
So far I have tried this:
WITH cte_base as(
SELECT DISTINCT ID, statusID
FROM testtable
)
SELECT *
FROM cte_base
IF EXISTS(SELECT * FROM Newtable WHERE EXISTS (SELECT ID FROM cte_base))
UPDATE newtable
SET statusID = 2
WHERE Newtable.ID = cte_base.ID
ELSE
INSERT INTO newtable(ID, statusID)
SELECT ID, statusID
FROM cte_base
WHERE Newtable.ID <> cte_base.ID
I have to run this query against live data, hence I would like to know if my logic is correct.
Basic merge example based on your provided code.
MERGE INTO NewTable AS T
USING
(
SELECT DISTINCT ID,statusID
FROM testtable
) AS S
ON S.ID = T.ID
WHEN MATCHED THEN SET
T.StatusID = 2
WHEN NOT MATCHED INSERT (ID,statusID)
VALUES (S.ID,S.statusID)
;
What are you trying to do?
EXISTS (SELECT ID FROM cte_base)
If cte_base has any records that will be true every time
That is no different than
SELECT DISTINCT ID, statusID
FROM testtable
And will be true every time if there are any records in testtable

SQL query for finding percentage of new records in a table

I have two tables Table1 and Table2.
Each of these tables have columns Column1, Column2.
I need to find percentage of new Column1 in Table1 group by Column2.
1) Count of New Records in Column1 = Count of (Distinct Column1
present in Table1 and not in Table2).
2) Count of distinct Column1 in TableOne
Percentage = (1 / 2) * 100.
What I tried is
select count(distinct column1)
from TableOne left outer join TableTwo on
(tableone.column1=tabletwo.column2)
where TableTwo.column1 is null.
And this:
select count(distinct column1) from tableone.
Now how to combine both in a single query and do group by column2.
Quick way to do it is:
select ((countA/countB)*100) as Percentage (
select count(distinct column1) as countA,
(select count(distinct column1) from tableone) as countB
from TableOne left outer join TableTwo on
(tableone.column1=tabletwo.column2)
where TableTwo.column1 is null) as X
from X
For grouping by column2, you just have to add it to the query. But need to know by which column2 you want to group it.
If you need any cross reference in between tables (1 & 2) It'll be a bit more complicated.
DECLARE #COUNT1 INT
DECLARE #COUNT2 INT
SELECT #COUNT1 = COUNT(*) FROM comparetable
SELECT #COUNT2 = COUNT(*) FROM comparetable WHERE Description IS NOT NULL
SELECT CAST(CAST(#COUNT2 AS DECIMAL(10,2) )/CAST(#COUNT1 AS DECIMAL(10,2)) AS DECIMAL(10,2)) AS PERCENTAGE

How to write the query that returns records where some column value appears more than once?

I have a table that has column with statuses. I need to write the query that returns records where some column value appears more than once?
Something like this:
select * from Table1
where COUNT(StatusID = 6) > 1
You can write your query like following:
SELECT *
FROM Table1
WHERE StatusID IN
(
SELECT StatusID
FROM (SELECT StatusID,Count(*) AS cnt FROM Table1 WHERE StatusID=6
GROUP BY StatusID
HAVING COUNT(*) > 1) AS tbl
)

Count uid from two tables who look the same sort by tablename

since I am not as good with more complex SQL SELECT Statements I thought of just asking here, since it's hard to find something right on topic.
I got two tables who have exactly the same structure like
TABLE A (id (INT(11)), time (VARCHAR(10));)
TABLE B (id (INT(11)), time (VARCHAR(10));)
Now I want a single SELECT to count the entrys of an specific id in both tables.
SELECT COUNT(*) FROM TABLE A WHERE id = '1';
SELECT COUNT(*) FROM TABLE B WHERE id = '1';
So I thought it would be much better for the database performance if I use one SELECT instead of one.
Thanks for helping out
SELECT COUNT(*) as count, 'tableA' as table_name FROM TABLEA WHERE id = '1'
union all
SELECT COUNT(*), 'tableB' FROM TABLEB WHERE id = '1'
If you want the separate counts in a single row, you can use subqueries
SELECT
(SELECT COUNT(*) FROM TABLE A WHERE id = '1') a_count,
(SELECT COUNT(*) FROM TABLE B WHERE id = '1') b_count;
You could do it like:
select count(*)
from (
select id from t1 where id = 1
union all
select id from t2 where id = 1
) as t
Another alternative is:
select sum(cnt)
from (
select count(*) as cnt from t1 where id = 1
union all
select count(*) as cnt from t2 where id = 1
) as t

SQL Server Top 1

In Microsoft SQL Server 2005 or above, I would like to get the first row, and if there is no matching row, then return a row with default values.
SELECT TOP 1 ID,Name
FROM TableName
UNION ALL
SELECT 0,''
ORDER BY ID DESC
This works, except that it returns two rows if there is data in the table, and 1 row if not.
I'd like it to always return 1 row.
I think it has something to do with EXISTS, but I'm not sure.
It would be something like:
SELECT TOP 1 * FROM Contact
WHERE EXISTS(select * from contact)
But if not EXISTS, then SELECT 0,''
What happens when the table is very full and you might want to specify which row of your top 1 to get, such as the first name? OMG Ponies' query will return the wrong answer in that case if you just change the ORDER BY clause. His query also costs about 8% more CPU than this modification (though it has equal reads)
SELECT TOP 1 *
FROM (
SELECT TOP 1 ID,Name
FROM TableName
ORDER BY Name
UNION ALL
SELECT 0,''
) X
ORDER BY ID DESC
The difference is that the inner query has a TOP 1 also, and which TOP 1 can be specified there (as shown).
Just for fun, this is another way to do it which performs very closely to the above query (-15ms to +30ms). While it's more complicated than necessary for such a simple query, it demonstrates a technique that I don't see other SQL folks using very often.
SELECT
ID = Coalesce(T.ID, 0),
Name = Coalesce(T.Name, '')
FROM
(SELECT 1) X (Num)
LEFT JOIN (
SELECT TOP 1 ID, Name
FROM TableName
ORDER BY ID DESC
) T ON 1 = 1 -- effective cross join but does not limit rows in the first table
Use:
SELECT TOP 1
x.id,
x.name
FROM (SELECT t.id,
t.name
FROM TABLENAME t
UNION ALL
SELECT 0,
'') x
ORDER BY id DESC
Using a CTE equivalent:
WITH query AS (
SELECT t.id,
t.name
FROM TABLENAME t
UNION ALL
SELECT 0,
'')
SELECT TOP 1
x.id,
x.name
FROM query x
ORDER BY x.id DESC
CREATE TABLE #sample(id INT, data VARCHAR(10))
SELECT TOP 1 id, data INTO #temp FROM #sample
IF ##ROWCOUNT = 0 INSERT INTO #temp VALUES (null, null)
SELECT * FROM #temp
put the top oustide of the UNION query
SELECT TOP 1 * FROM(
SELECT ID,Name
FROM TableName
UNION ALL
SELECT 0,''
) z
ORDER BY ID DESC
IF EXISTS ( SELECT TOP 1 ID, Name FROM TableName )
BEGIN
SELECT TOP 1 ID, Name FROM TableName
END
ELSE
BEGIN
--exists returned no rows
--send a default row
SELECT 0, ''
END