select same records multiple times with one column value changed in SQL - sql

I have getting same records multiple times with one column value changed using union like this.
Select col1, col2, 'A' as col3
Union
Select col1, col2, 'B' as col3
Union
Select col1, col2, 'C' as col3
I want to know if there is any way to do this in single query instead of writing 3 queries. Can someone please help?

I simple CROSS JOIN with the specified VALUES should do the trick
Select Col1,Col2,Col3
From YourTable A
Cross Join (Values ('A'),('B'),('C') ) B (Col3)

SELECT d.name, x.field1
FROM sys.databases d
, (VALUES('A'), ('B'), ('C')) AS x(field1)
You should look up the cross join syntax but this is an example off how to do it.

Related

SQL - Transposing rows from some columns in a table to each record in thesame table

I am using a platform which accepts minimal SQL functions to write a SQL code. The UNPIVOT function cannot be used on the platform so I have to do this manually. I am thinking along the line of UNION ALL and then CROSS JOINING (which I attempted but ended up with the wrong record counts. Please see image attached.
Any help / pointer will be highly appreciated!
I don't know how you used UNION ALL but it can be done like this:
select col1, col2, col3 as NewCol from Table1
union all
select col1, col2, col4 from Table1
You could also use an ORDER BY clause, so that rows with the same col1 and col2 appear in subsequent rows:
select col1, col2, NewCol
from (
select col1, col2, col3 as NewCol, 1 as ord from Table1
union all
select col1, col2, col4, 2 from Table1
) t
order by col1, col2, ord
A portable approach uses union all:
select col1, col2, col3 as newcol from mytable
union all
select col1, col2, col4 from mytable
If your database supports lateral joins (also called cross apply in some databases) and values(), this can be simplified:
select t.col1, t.col2, x.newcol
from mytable t
cross join lateral (values(col3), (col4)) x(newcol)
You can use a cross join, but it requires some case logic. The exact syntax depends on the database, but something like this:
select t.col1, t.col2,
(case when n.n = 1 then t.col3 else t.col4 end) as newcol
from t cross join
(select 1 as n union all select 2) n;
To load another table, you would do one of the following:
insert these results into a table that has already been created.
Use select into or create table as depending on the database.
If you care about the ordering, then you can add order by t.col1, t.col2, n.n.
In most cases, a simple union all approach is fine (such as GMB suggests). That approach requires scanning the table twice, which incurs some additional overhead. However, if the "table" is really a complex query or view, then only processing it once is a bigger advantage.

SQL: INSERT multiple different hardcoded values in one column

I could not find a solution for this yet. I want to insert multiple rows with 2 or more different hardcoded values, but also with data that I get from another table.
Example: I want to add 2 items into a table for a user that has the ID = '0' in another table without running 2 queries.
This is what I've done so far:
INSERT INTO
DB.dbo.Table WITH(ROWLOCK, XLOCK) (
col1,
col2,
col3,
col4
)
SELECT
DISTINCT customer_id,
hardcoded_value1,
constant1,
constant2
FROM
DB.dbo.Other_Table
WHERE
ID = '0';
You could cross join your select query with a table value constructor that holds several records with harcoded values. This will generate as many rows as provided in the table value constructor for each row return by the query.
INSERT INTO
DB.dbo.Table WITH(ROWLOCK, XLOCK) (
col1,
col2,
col3,
col4
)
SELECT
DISTINCT t.customer_id,
x.hardcoded_value,
t.constant1,
t.onstant2
FROM DB.dbo.Other_Table t
CROSS JOIN (VALUES ('harcoded 1'), ('harcoded 2')) as x(hardcoded_value)
WHERE t.ID = '0';
I can't tell from your question what the basis is for the different values. You may be able to use a CASE statement to insert different hardcoded values based on some criteria:
INSERT INTO
DB.dbo.Table WITH(ROWLOCK, XLOCK) (
col1,
col2,
col3,
col4
)
SELECT
DISTINCT customer_id,
CASE WHEN Condition1 THEN hardcoded_value1
WHEN Condition2 THEN hardcoded_value2
...
END,
constant1,
constant2
FROM
DB.dbo.Other_Table
WHERE
ID = '0';

SQL script for retrieving 5 unique values in a table ( google big query )

I am looking for a query where I can get unique values(5) in a table. For example.
The table consists of more 100+ columns. Is there any way I can get unique values.
I am using google big query and tried this option
select col1 col2 ... coln
from tablename
where col1 is not null and col2 is not null
group by col1,col2... coln
order by col1, col2... coln
limit 5
But problem is it gives zero records if all the column are null
Thanks
R
I think you might be able to do this in Google bigquery, assuming that the types for the columns are compatible:
select colname, colval
from (select 'col1' as colname, col1 as colvalue
from t
where col1 is not null
group by col1
limit 5
),
(select 'col2' as colname, col2 as colvalue
from t
where col2 is not null
group by col2
limit 5
),
. . .
For those not familiar with the syntax, a comas in the from clause means union all, not cross join in this dialect. Why did they have to change this?
Try This one, i hope it works
;With CTE as (
select * ,ROW_NUMBER () over (partition by isnull(col1,''),isnull(col2,'')... isnull(coln,'') order by isnull(col1,'')) row_id
from tablename
) select * from CTE where row_id =1

merge two queries with different where and different grouping into 1

Sorry, I asked this question just before and got some good answers but then I realised I made a mistake with the query in question, if I change the question in the original post that could make the answers invalid so I'm posting again with the right query this time, please forgive me, I hope this is acceptable.
DECLARE #Temp TABLE
(MeasureDate, col1, col2, type)
INSERT INTO #Temp
SELECT MeasureDate, col1, col2, 1
FROM Table1
WHERE Col3 = 1
INSERT INTO #Temp
SELECT MeasureDate, col1, col2, 3
FROM Table1
WHERE Col3 = 1
AND Col4 = 7000
SELECT SUM(col1) / SUM(col2) AS Percentage, MeasureDate, Type
FROM #Temp
GROUP BY MeasureDate, Type
I do two inserts into the temp table, 2nd insert with an extra WHERE but same columns same table, but different type, then I do SUM(col1) / SUM(col2) on the temp table to return the result I need per MeasureDate and type. Is there a way to merge all these inserts and selects into one statement so I don't use a temp table and do a single select from Table1? Or even if I still need the temp table, merge the selects into one select instead of two separate selects? Stored procedure works fine as it is, just looking for a way to shorten it.
Thanks.
Sure can. I might start with combining the two queries from your inserts using UNION ALL (this variation of UNION will not remove duplicates), wrapped up in a CTE from which you can perform your final query:
WITH MeasureData(MeasureDate, col1, col2, type) AS (
SELECT MeasureDate, col1, col2, 1
FROM Table1
WHERE Col3 = 1
UNION ALL
SELECT MeasureDate, col1, col2, 3
FROM Table1
WHERE Col3 = 1
AND Col4 = 7000
)
SELECT SUM(col1) / SUM(col2) AS Percentage, MeasureDate, Type
FROM MeasureData
GROUP BY MeasureDate, Type
That's it, no more table variable or insert statements.
No real need for a UNION, you can handle this with a CASE statement:
SELECT SUM(col1) / SUM(col2) AS Percentage, MeasureDate, Type
FROM (
SELECT MeasureDate, col1, col2, case when Col4 = 7000 then 3 else 1 end type
FROM Table1
WHERE Col3 = 1
) t
GROUP BY MeasureDate, Type
Edit, as Gordon correctly points out, for Type = 1, this query wouldn't produce the same results. Here's a variation on Gordon's good answer that might be easier to visually understand using a CROSS JOIN and IF logic:
SELECT T1.MeasureDate,
T.Type,
SUM(IF(T.Type=1,Col1,IF(T.Type=3 AND T1.Col4=7000,T1.Col1,0))) /
SUM(IF(T.Type=1,Col2,IF(T.Type=3 AND T1.Col4=7000,T1.Col2,0))) AS Percentage
FROM Table1 T1
CROSS JOIN (SELECT 1 Type UNION SELECT 3) T
WHERE T1.Col3 = 1
GROUP BY T1.MeasureDate, T.Type
Condensed SQL Fiddle
Your method is double counting cases where col3 = 1 and col4 = 7000. Here is a method that takes this into account, without union on the overall table:
select t.type, SUM(t1.col1) / SUM(t1.col2) AS Percentage, t1.MeasureDate, t.Type
from table1 t1 join
(select 1 as type union all
select 3 as type
) t
on t.type = 1 or t1.col4 = 7000
where t1.col3 = 1
group by measuredate, type;

Inserting multiple select statements into a table as values

Is it possible to do something like this in SQL Server:
INSERT INTO MyTable (Col1,Col2,Col3,Col4,Col5,Col6,Col7) VALUES
SELECT Col1 FROM Func1(),
SELECT Col2 FROM Func2(),
SELECT Col3,Col4,Col5 FROM Func3(),
SELECT Col6 FROM Func4(),
SELECT Col7 FROM Func5()
I have a large number of functions which return one-value results and one function which returns 3 columns. I would like to insert all of this data into one row of a table?
I can see the function returning muliple columns as possibly being a problem?
If all functions return just one row...
INSERT INTO
MyTable (Col1,Col2,Col3,Col4,Col5,Col6,Col7)
SELECT
f1.col1, f2.col2, f3.col3, f3.col4, f3.col5, f4.col6, f5.col7
FROM
(SELECT Col1 FROM Func1()) AS f1
CROSS JOIN
(SELECT Col2 FROM Func2()) AS f2
CROSS JOIN
(SELECT Col3,Col4,Col5 FROM Func3()) AS f3
CROSS JOIN
(SELECT Col6 FROM Func4()) AS f4
CROSS JOIN
(SELECT Col7 FROM Func5()) AS f5
If the functions return more than one row, you need to join them in the normal way; with predicates that determine which left row gets joined to which right row.
INSERT INTO MyTable (Col1,Col2,Col3,Col4,Col5,Col6,Col7) VALUES
SELECT Col1 FROM Func1(),
SELECT Col2 FROM Func2(),
SELECT Col3 FROM (SELECT Col3,Col4,Col5 FROM Func3()),
SELECT Col4 FROM (SELECT Col3,Col4,Col5 FROM Func3()),
SELECT Col5 FROM (SELECT Col3,Col4,Col5 FROM Func3())
SELECT Col6 FROM Func4(),
SELECT Col7 FROM Func5()
You have to remove Values and all ","and brackets around each select statement.