Union different tables with differents columns and data - sql

My problem is that I have 4 differents SELECT with
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1
I want that the results appear together whith the respective names like:
regular rptmm new rptss
10 5 2 6

Firstly, I'd suggest not to use Count()*. There are many answers on this site explaining why so I am not going to repeat it.
Instead, I'd suggest you to use a query like this:
SELECT (SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 1) AS 'Regular',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 1 AND tab.bl = 0) AS 'rptmm',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 0) AS 'New',
(SELECT COUNT (tab.someColumnName)
FROM TableName tab
WHERE tab.experience = 0 AND tab.bl = 1) AS 'rptss'
Hope this helps!!!

Just put UNION ALL between your four statements you will get four rows with each count on its own row. However, you will lose the column name. You could also use join to get one row with four columnes. Just put the keyword join between each sql statement.
SELECT COUNT (*) AS regular
WHERE experience = 1 AND bl = 1
JOIN
SELECT COUNT (*) AS rptmm
WHERE experience = 1 AND bl = 0
JOIN
SELECT COUNT (*) AS new
WHERE experience = 0 AND bl = 0
JOIN
SELECT COUNT (*) AS rptss
WHERE experience = 0 AND bl = 1

You could create a temp table to hold all of this data for you: Replace Name1, Name2, Name3,Name4 with whatever you want to call them. These will be the column headers.
CREATE TABLE #Temp(
NAME1 INT
,NAME2 INT
,NAME3 INT
,NAME4 INT
)
INSERT INTO #Temp
(NAME1)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 1
INSERT INTO #Temp
(NAME2)
SELECT COUNT(*) AS regular
WHERE experience = 1 AND bl = 0
INSERT INTO #Temp
(NAME3)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 0
INSERT INTO #Temp
(NAME4)
SELECT COUNT(*) AS regular
WHERE experience = 0 AND bl = 1*
SELECT * FROM #Temp

Related

I just started learning SQL and I couldn't do the query, can you help me?

There is a field in the sql query that I can't do. First of all, a new column must be added to the table below. The value of this column needs to be percent complete, so it's a percentage value. So for example, there are 7 values from Cupboard=1 shelves. Where IsCounted is here, 3 of them are counted. In other words, those with Cupboard = 1 should write the percentage value of 3/7 as the value in the new column to be created. If the IsCounted of the others is 0, it will write zero percent. How can I do this?
My Sql Code:
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
(CASE WHEN ToplamSayım > 0 THEN 1 ELSE 0 END) AS IsCounted
FROM (SELECT p.RegionName,
r.Shelf,
r.Cupboard,
(SELECT COUNT(*)
FROM FAZIKI.dbo.PM_ProductCountingNew
WHERE RegionCupboardShelfTypeId = r.Id) AS ToplamSayım
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45) a
ORDER BY a.RegionName;
The result is as in the picture below:
It looks like a windowed AVG should do the trick, although it's not entirely clear what the partitioning column should be.
The SELECT COUNT can be simplified to an EXISTS
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
a.IsCounted,
AVG(a.IsCounted * 1.0) OVER (PARTITION BY a.RegionName, a.Cupboard) Percentage
FROM (
SELECT p.RegionName,
r.Shelf,
r.Cupboard,
CASE WHEN EXISTS (SELECT 1
FROM FAZIKI.dbo.PM_ProductCountingNew pcn
WHERE pcn.RegionCupboardShelfTypeId = r.Id
) THEN 1 ELSE 0 END AS IsCounted
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45
) a
ORDER BY a.RegionName;

Conditional for a field generated by a SELECT statement

SELECT
Req_PK,
Req_PostDate,
Req_code,
Req_CreateDate,
Req_FillDate,
Req_Canceldate,
Req_Hold,
(
Select Convert(varchar(50),Count(CanReq_PK))
From CanReq
Where CanReq_ReqFK = Req_PK) AS Applications,
Req_PublishstatusFK
FROM Req
WHERE Req_Filled <> 1
AND Req_Cancelled <> 1
AND Req_Template <> 1
AND Req_PublishstatusFK = 1
AND Req_publishstatusfk = 1
How do I modify this query so the Applications field/alias is not the everything returned by the SELECT statement but everything except the ones with value '0'?
Help is very much appreciated!
Use an explicit JOIN instead:
SELECT r.Req_PK, r.Req_PostDate, r.Req_code, r.Req_CreateDate, r.Req_FillDate,
r.Req_Canceldate, r.Req_Hold,
cr.num_Applications,
r.Req_PublishstatusFK
FROM Req r JOIN
(SELECT cr.CanReq_ReqFK, Count(*) as num_applications
FROM CanReq cr
GROUP BY cr.CanReq_ReqFK
) cr
ON cr.CanReq_ReqFK = r.Req_PK
WHERE r.Req_Filled <> 1 AND r.Req_Cancelled <> 1 AND r.Req_Template <> 1 AND
r.Req_PublishstatusFK = 1 AND r.Req_publishstatusfk = 1;
This will filter out any rows that don't have a record in CanReq -- the ones that would have a count of 0 in your version of the query.
I don't know why you would want the count to be a string. Of course, you can include the conversion if you need it, but it doesn't seem necessary to me.

SQL Implementing 'IN' operator with 'OR'

I am working on a legacy system which has a custom java implementation for generating SQL queries. That doesn't support 'IN' operation.
To implement 'IN' I have written something like
SELECT * from Q
WHERE IS_HIDDEN = 0 AND ID = 1
OR ID = 2 OR ID = 3 AND IS_DELETED = 0;
I know that the one like below would have been fine.
SELECT * from Q
WHERE IS_HIDDEN = 0 AND (ID = 1
OR ID = 2 OR ID = 3) AND IS_DELETED = 0 ;
Both these return the same result but I'm not too confident about SQL operator priorities. I had read that AND takes precedence
Is it safe to assume that both the SQL statemets are equivalent.
The actual query that I wanted to write is
SELECT * from Q
WHERE IS_HIDDEN = 0 AND ID IN(1, 2, 3) AND IS_DELETED = 0;
The DB in question is oracle 10g.
Update: The reason that this was working is because the oracle CBO rearranges the subclauses in the where clause.
No your queries are not the same
SELECT * from Q
WHERE IS_HIDDEN = 0 AND ID = 1
OR ID = 2 OR ID = 3 AND IS_DELETED = 0;
is like
SELECT * FROM Q WHERE IS_HIDDEN = 0 AND ID = 1
UNION
SELECT * FROM Q WHERE ID = 2
UNION
SELECT * FROM Q WHERE ID = 3 AND IS_DELETED = 0
when you use the parentheses for your ORs then you have the same like the IN-Clause
You can try it: SQLFiddle
You first query is equal to the IN. You should use that:
Your second query is like this:
SELECT * from Q
WHERE (IS_HIDDEN = 0 AND ID = 1) OR ID = 2 OR (ID = 3 AND IS_DELETED = 0);
If IS_HIDDEN is 1 or DELETED Is 1, but ID is 2, your query will still give you records. Try it..

Join Two Select Statements With Different Columns And Condition

I'm not good at asking question, so i'll give an example of what i want to have.
if i = 1 and xi = 0 then
select a,b,c,d,e,f,g where z = 1
elseif i=0 and xi = 1 then
select a,c,f,h,l,n where w = var
elseif i=1 and xi=1 then
select a,b,c,d,e,f,g, where z = 1
union all
select a,c,f,h,l,n where w = var
end if
How can I join the 2 select statement if their columns are not equal and they both have a unique condition?
Based on the conditions you can create derived tables to fetch desired columns and then to get a union of the two tables add null values in column list of derived tables which have less number of columns:
Pseudo code:
select * from
(select a,b,c,d,e,f,g
where z = 1
and 1 = case when i = 1 and xi = 0 then 1
when i = 1 and xi = 1 then 1
else 0
end) as T1
union all
(select a,c,f,h,l,n ,null -- add null value to equate number of columns
where w = var
and 1 = case when i=0 and xi = 1 then 1
when i=1 and xi = 1 then 1
else 0
end) as T2
Hope this helps!!!
If it is not a requirement not to use dynamic sql I will opt for that one.
Another idea will be to use user defined function returnin tables.
So you encapsulate there the logic...

SQL retrieval from tables

I have a table something like
EMPLOYEE_ID DTL_ID COLUMN_A COLUMN_B
---------------------------
JOHN 0 1 1
JOHN 1 3 1
LINN 0 1 12
SMITH 0 9 1
SMITH 1 11 12
It means for each person there will be one or more records with different DTL_ID's value (0, 1, 2 .. etc).
Now I'd like to create a T-SQL statement to retrieve the records with EMPLOYEE_ID and DTL_ID.
If the specified DTL_ID is NOT found, the record with DTL_ID=0 will be returned.
I know that I can achieve this in various ways such as checking if a row exists via EXISTS or COUNT(*) first and then retrieve the row.
However, I'd like to know other possible ways because this retrieval statement is very common in my application and my table have hundred thousand of rows.
In the above approach, I've had to retrieve twice even if the record with the DTL_ID specified exists, and I want to avoid this.
Like this:
SELECT *
FROM table
WHERE EMPLOYEE_ID = ?? AND DTL_ID = ??
UNION
SELECT *
FROM table
WHERE EMPLOYEE_ID = ?? AND DTL_ID = 0
AND NOT EXISTS (SELECT *
FROM table
WHERE EMPLOYEE_ID = ?? AND DTL_ID = ??)
You will of course have to fill in the ?? with the proper number.
If DTL_ID is always 0 or positive:
SELECT TOP 1 * FROM table
where EmployeeID = #EmployeeID and DTL_ID in (#DTL_ID,0)
order by DTL_ID desc
If you're working across multiple employees in a single query, etc, then you might want to use ROW_NUMBER() if your version of SQL supports it.
Use ISNULL(DTL_ID, 0) in your final SELECT query
SELECT E1.EMPLOYEE_ID, ISNULL(E2.DTL_ID, 0), E1.COLUMN_A, E1.COLUMN_B EMPLIYEES AS E1
LEFT JOIN EMPLIYEES AS E2
ON E1.EMPLOYEE_ID = E2.EMPLOYEE_ID AND E2.DTL_ID = 42
You can use top and union, e.g.:
declare #t table(id int, value int, c char)
insert #t values (1,0,'a'), (1,1,'b'), (1,2,'c')
declare #id int = 1;
declare #value int = 2;
select top(1) *
from
(
select *
from #t t
where t.value = #value and t.id = #id
union all
select *
from #t t
where t.value = 0
)a
order by a.value desc
If #value = 2 than query returns 1 2 c. If #value = 3 than query returns 1 0 a.
SELECT MAX(DTL_ID) ...
WHERE DTL_ID IN (#DTL_ID, 0)