So sorry but I am new to SQL querying and could use a little help.
I will like to join results from 2 tables and I can't seem to get it return results I need.
Query 1
select c1,c2,c3,c4,c5,c6,c7
from t1
where (c3 between cast(dateadd(day, -1,Getdate()) AS Date and cast(dateadd(day,0,getdate()) as date))
Query 2
select c1,c2,c3,c4,c5,c6
from t2
where c2 in ('user', 'connected', 'agent') and
(c3 between cast(dateadd(day, -1,Getdate()) AS Date and cast(dateadd(day,0,getdate()) as date))
I tried using union all but I get an error must have equal number of expressions in their target lists.
Any assistance will be appreciated.
When using an union, both queries must have the same number of fields in the select statements. Query 1 has 7 items while query 2 has 6. You can add a null value to query 2.
Related
I have two tables one for receiving "PO_RECVR_HIST" and other table for sales "PS_TKT_HIST_LIN". I want to create a query showing the total for receiving and total for sales. The two dates are not related the results come wrong. The two tables has the same vendor. I am using the following query
SELECT P.VEND_NO,
sum(P.RECVR_TOT)AS RECV_TOT,
sum(S.CALC_EXT_PRC) AS SAL_TOT
FROM PO_RECVR_HIST P INNER JOIN
PS_TKT_HIST_LIN S
ON P.VEND_NO = S.ITEM_VEND_NO
WHERE P.RECVR_DAT > getdate()-7
GROUP BY P.VEND_NO, S.BUS_DAT
HAVING S.BUS_DAT > getdate()-7
ORDER BY P.VEND_NO
Any advise please?
I think I get it. You want the sums in different columns. One approach is to do a UNION ALL to get the data together, and then aggregate:
SELECT VEND_NO,
SUM(RECVR_TOT)AS RECV_TOT,
SUM(CALC_EXT_PRC) AS SAL_TOT
FROM ((SELECT P.VEND_NO, P.RECVR_DAT as dte, P.RECVR_TOT, 0 as CALC_EXT_PRC
FROM PO_RECVR_HIST P
) UNION ALL
(SELECT S.ITEM_VEND_NO, S.BUS_DAT, 0, CALC_EXT_PRC
FROM PS_TKT_HIST_LIN S
)
) PS
WHERE DTE > GETDATE() - 7
GROUP BY P.VEND_NO
ORDER BY P.VEND_NO;
A JOIN is just not a good approach because it will throw off the aggregation.
Wonder if someone could cast an eye over the following problem:
I'm running a SQL SELECT statement which gives me the following results:
DATE NumberOfHours
2017-05-01 4
2017-06-01 38
2017-07-01 68
And what I'm trying (like to be able to) to do is off the back of this table create another table that contains 4 rows for 2017-05-01, 38 Rows for 2017-06-01 and 68 rows for 2017-07-01. So I end up with a table that's got 110 rows in it.
I'm at a bit of a loss as to how this could be achieved...could anyone assist?
////////////////////////////////////////////////////////////
Using the response listed by Gordon Linoff I managed to get this working working by using:
with cte as (
SELECT DATEADD(month, datediff(month,0,L.DateAdded),0) AS 'Date', CEILING(SUM(l.CPDHours))AS NumberOfHours
FROM WebsiteICA_SF.dbo.CPD_Log L
WHERE L.DateAdded >= DATEADD(month, -6, GETDATE())
AND (L.Provider = 'ICA' OR L.Provider like 'International Compli%')
GROUP BY DATEADD(month, datediff(month,0,L.DateAdded),0)
union all
select date, NumberOfHours - 1
from cte
where NumberOfHours > 1
)
select 1 AS 'ObId', date, 'ICA' AS Provider, '# ICA' AS DataType
from cte
order by DATEADD(month, datediff(month,0,cte.Date),0)
OPTION (maxrecursion 10000);
One simple method is a recursive CTE:
with cte as (
select date, NumberOfHours
from t
union all
select date, NumberOfHours - 1
from cte
where NumberOfHours > 1
)
select date
from cte;
By default, this is limited to a maximum of 100 hours. However, that is easily changed using the MAXRECURSION option.
Other methods generally rely on a second table to generate numbers. I also like this approach because it is a gentle introduction to recursive CTEs.
Here is a nice SQL Fiddle.
So you have a result set with 3 rows and one column in it which tells you how many rows it represents. You want to generate that many rows.
Not sure what you want to store in that, but here is a solution to the base problem:
Create a table (temp table or CTE is fine too) which contains only one column, storing numbers from 0 to whatever. This is called Tally Table or Numbers Table.
Join this table to your resultset:
WITH NumbersCTE AS (
-- This will give you a bunch of Numbers
-- Persist a table if you want to use it more frequently
SELECT ROW_NUMBER() OVER (ORDER BY name) AS Number FROM sys.columns
)
SELECT
MT.Date,
N.Number
FROM
dbo.MyTable MT
INNER JOIN NumbersCTE N
ON N.Number <= MT.NumberOfHours
As Pieter Geerkens pointed out in the comments, the above method is not the best to generate a numbers table, but for demostration puposes it is fine.
For more info about how to generat tally tables in SQL Server, you can check
http://www.sqlservercentral.com/blogs/dwainsql/2014/03/27/tally-tables-in-t-sql/
Please Correct my query to Select data.
If there is an entry in LeaveApply Table having given date betwwn a from date and to date in the table, i should get the pK of table else zero.
please help
Select A,
B,
ISNULL((select LeaveApply_Id from Tbl_Stud_Leave_Apply where Candidate_Id=120
and ('01/13/2014 12:00:00 AM' between Stud_LeaveFromDate and Stud_LeaveToDate)),0) As Leave from TableA where Condition.
You have to apply the isnull to the column, not to the whole query.
Try the below
select ISNULL(LeaveApply_Id,0) AS ID from Tbl_Stud_Leave_Apply
where Candidate_Id= #Candidate and (#date between Stud_LeaveFromDate and Stud_LeaveToDate)
In the above #Candidate and #date are dynamically passed to query.
Note that if you do the lookup across a lot of results, you should consider a set-based approach to the lookup, e.g.
SELECT
c.*,
ISNULL(l.LeaveApply_Id, 0) AS IsLeave
FROM
Candidates c
LEFT OUTER JOIN Tbl_Stud_Leave_Apply l
on l.Candidate_Id=c.ID AND #Date between Stud_LeaveFromDate and Stud_LeaveToDate;
I have the following statement:
SELECT
(CONVERT(VARCHAR(10), f1, 120)) AS ff1,
CONVERT(VARCHAR(10), f2, 103) AS ff2,
...,
Bonus,
Malus,
ClientID,
FROM
my_table
WHERE
<my_conditions>
ORDER BY
f1 ASC
This select returns several rows for each ClientID. I have to filter out all the rows with the Clients that don't have any row with non-empty Bonus or Malus.
How can I do it by changing this select by one statement only and without duplicating all this select?
I could store the result in a #temp_table, then group the data and use the result of the grouping to filter the temp table. - BUT I should do it by one statement only.
I could perform this select twice - one time grouping it and then I can filter the rows based on grouping result. BUT I don't want to select it twice.
May be CTE (Common Table Expressions) could be useful here to perform the select one time only and to be able to use the result for grouping and then for selecting the desired result based on the grouping result.
Any more elegant solution for this problem?
Thank you in advance!
Just to clarify what the SQL should do I add an example:
ClientID Bonus Malus
1 1
1
1 1
2
2
3 4
3 5
3 1
So in this case I don't want the ClientID=2 rows to appear (they are not interesting). The result should be:
ClientID Bonus Malus
1 1
1
1 1
3 4
3 5
3 1
SELECT Bonus,
Malus,
ClientID
FROM my_table
WHERE ClientID not in
(
select ClientID
from my_table
group by ClientID
having count(Bonus) = 0 and count(Malus) = 0
)
A CTE will work fine, but in effect its contents will be executed twice because they are being cloned into all the places where the CTE is being used. This can be a net performance win or loss compared to using a temp table. If the query is very expensive it might come out as a loss. If it is cheap or if many rows are being returned the temp table will lose the comparison.
Which solution is better? Look at the execution plans and measure the performance.
The CTE is the easier, more maintainable are less redundant alternative.
You haven't specified what are data types of Bonus and Malus columns. So if they're integer (or can be converted to integer), then the query below should be helpful. It calculates sum of both columns for each ClientID. These sums are the same for each detail line of the same client so we can use them in WHERE condition. Statement SUM() OVER() is called "windowed function" and can't be used in WHERE clause so I had to wrap your select-list with a parent one just because of syntax.
SELECT *
FROM (
SELECT
CONVERT(VARCHAR(10), f1, 120) AS ff1,
CONVERT(VARCHAR(10), f2, 103) AS ff2,
...,
Bonus,
Malus,
ClientID,
SUM(Bonus) OVER (PARTITION BY ClientID) AS ClientBonusTotal,
SUM(Malus) OVER (PARTITION BY ClientID) AS ClientMalusTotal
FROM
my_table
WHERE
<my_conditions>
) a
WHERE ISNULL(a.ClientBonusTotal, 0) <> 0 OR ISNULL(a.ClientMalusTotal, 0) <> 0
ORDER BY f1 ASC
I have this query, and I want to get the results of both of these queries. Note that machine_output is a view I created :
SELECT DISTINCT tblcertified.employeenumber,
tblcertified.machinenumber
FROM tblcertified
INNER JOIN machine_output
ON tblcertified.machinenumber = machine_output.machinenumber
UNION
SELECT CONVERT (DATE, tblperiod.fromdate) AS fDate,
tblscheduled.employeenumber
FROM tblperiod
INNER JOIN tblscheduled
ON tblperiod.number = tblscheduled.number
WHERE tblperiod.fromdate BETWEEN Dateadd(m, -3, Getdate()) AND Getdate()
When running the above, I get the following error:
Msg 241, Level 16, State 1, Line 1 Conversion failed when converting
date and/or time from character string.
I also get this error when I drop the convert statement.
Your first column in the first subquery is called EmployeeNumber.
Your first column in the second table is being converted to Date.
I don't think you want a union, but you are familiar with joins. Your select lists needs to match for a union.
If you want to fix this, change the first select to something like:
select distinct cast(NULL as date) as fDate, tblcertified.employeenumber, tblcertified.machinenumber
and the second select to something like:
SELECT CONVERT (DATE, tblperiod.fromdate) AS fDate,
tblscheduled.employeenumber , NULL
As a join, your query would look something like this:
SELECT DISTINCT CONVERT (DATE, tblperiod.fromdate) AS fDate, tblcertified.employeenumber,
tblcertified.machinenumber
FROM tblcertified
INNER JOIN machine_output
ON tblcertified.machinenumber = machine_output.machinenumber
INNER JOIN tblscheduled
on tblscheduled.employeenumber = tblcertified.employeenumber
INNER JOIN tblperiod
ON tblperiod.number = tblscheduled.number
WHERE tblperiod.fromdate BETWEEN Dateadd(m, -3, Getdate()) AND Getdate() ;
This is a bit of guess as to what you want (you have no sample data to make it clear). But, you can do all the joins in one query and pull out the columns you need.