SQL Server : INSERT INTO within a SELECT - sql

In SSRS 2008, my query is in the form
WITH CTE ( *that makes a list of dates, unfortunately only starting from today, not from whatever past date the report demands*)
SELECT
*a bunch of columns*
FROM
asimpletable p1
CROSS APPLY
(*CTE*) dates1
LEFT OUTER JOIN
(*demand list subquery with several selects pulling from several tables*) d1 ON (*simple.PartID AND CTE.demandDate*)
LEFT OUTER JOIN
(*supply list subquery with several selects pulling from several tables*) s1 ON (*yada*)
*..and 4 other joins to subqueries*
WHERE
*enough conditions that I don't want to copy it 6 times for 6 different INSERT INTO statements*
Because the CTE can only start from today, when I display all the select by date, any that was dated in the past are lumped out of order.
So I want to make a temp table to cross apply and feed in all the dates I need. I can see how to do it with 6 INSERT INTO, copying the joined subqueries, but not only would it look ugly, it would be worse to keep all the subqueries in sync.
I liked the sound of this, but can't see how to return the selects nor how to apply it to several subqueries https://stackoverflow.com/a/1101516/5612361.
Reason the CTE idea only starts from today:
SET #CTEStartDate = cast(getdate() as date);
SET #CTEEndDate = cast(dateadd(day,100,getdate()) as date);
WITH Dates(eaDate) AS (
SELECT #CTEStartDate AS eaDate --Select First day in range
UNION ALL
SELECT DATEADD(DAY, 1, eaDate) FROM Dates WHERE eaDate < #CTEEndDate --Add a record for every day in the range
)
When i try to use
SET #CTEStartDate = cast(dateadd(day,-30,getdate()) as date);
I get
For more information about this error navigate to the report server on
the local server machine, or enable remote errors
---------------------------- Cannot read the next data row for the dataset DataSet1. (rsErrorReadingNextDataRow)
---------------------------- An error has occurred during report processing. (rsProcessingAborted)
As soon as I take out that dateadd it resolves without a hitch.

Related

How can I create a query in SQL Server, using as base table a date function and linking it to another table?

I am trying to create a query using a function of dates and a table of shifts, which can show me the shifts of workers each day, when I have a shift or rest depending on the day,
What do I have: I have a date function that gives me a range of dates that I add, I attach an example:
I have a table of shifts, with only the days that a person has a shift, if a day has a break, the date or the row does not appear, I attach an example:
It can be seen that in the shift table there are only records when a person has a shift.
Problem: when I perform the join between the function and the shift table through the date field, the result is that it only shows me the record when it has a shift and no, it does not put the date when it has a break, I attach an example:
Desired result:
The idea is that when the worker has a break, the row will be blank, only showing the date and his ID, or saying the word break.
I hope you can help me. Thank you so much.
Use LEFT JOIN for avoiding few date missing which has transaction in table.
Use two subquery here for getting appropriate result. In first subquery function CROSS JOIN with transaction table where retrieving distinct id_trabajador for specified date range. If it doesn't do then id will blank in result where no transaction exists for specific id in a certain date. In second subquery retrieve all rows for given date range.
-- SQL Server
SELECT tmp.fecha, tmp.id_trabajador
, tmd.inicio, tmd.termino
, COALESCE(CAST(tmd.jornada AS varchar(20)), 'DESCANSO') jornada
FROM (SELECT * FROM shift_cmr..fnRangoFechas('01-sep-2021', '31-dec-2021') t
CROSS JOIN (SELECT id_trabajador
FROM shift_cmr..trabajadores_turnos_planificados
WHERE fecha BETWEEN '2021-09-01' AND '2021-12-31'
GROUP BY id_trabajador) tt
) tmp
LEFT JOIN (SELECT *
FROM shift_cmr..trabajadores_turnos_planificados
WHERE fecha BETWEEN '2021-09-01' AND '2021-12-31') tmd
ON tmp.fecha = tmd.fecha
AND tmp.id_trabajador = tmd.id_trabajador
You need to start with the date table and LEFT JOIN everything else
SELECT
dates.fecha,
sh.id_trabajador,
sh.inicio,
sh.termino,
jornada = ISNULL(CAST(sh.jornada AS varchar(10)), 'DESCANSO')
FROM shift_cmr..fnRangoFechas('01-sep-2021', '31-dec-2021') dates
LEFT JOIN shift_cmr..trabajadores_turnos_planificados sh
ON sh.fecha = dates.fecha
This only gives you one blank row per date. If you need a blank row for every id_trabajador then you need to cross join that
SELECT
dates.fecha,
t.id_trabajador,
sh.inicio,
sh.termino,
jornada = ISNULL(CAST(sh.jornada AS varchar(10)), 'DESCANSO')
FROM shift_cmr..fnRangoFechas('01-sep-2021', '31-dec-2021') dates
CROSS JOIN shift_cmr..trabajadores t -- guessing the table name
LEFT JOIN shift_cmr..trabajadores_turnos_planificados sh
ON sh.fecha = dates.fecha AND t.id_trabajador = sh.id_trabajador

Executing a Aggregate function within a case without Group by

I am trying to assign a specific code to a client based on the number of gifts that they have given in the past 6 months using a CASE. I am unable to use WITH (screenshot) due to the limitations of the software that I am creating the query in. It only allows for select functions. I am unsure how to get a distinct count from another table (transaction data) and use that as parameters in the CASE I have currently built (based on my client information table). Does anyone know of any workarounds for this? I am unable to GROUP BY clientID at the end of my query because not all of my columns are aggregate, and I only need to GROUP BY clientID for this particular WHEN statement in the CASE. I have looked into the OVER() clause, but I am needing my date range that I am evaluating to be dynamic (counting transactions over the last six months), and the amount of rows that I would be including is variable, as the transaction count month to month varies. Also, the software that I am building this in does not recognize the PARTITIONED BY parameter of the over clause.
Any help would be great!
EDIT:
it is not letting me attach an image... -____- I have added the two sections of code that I am looking for assistance with!
WITH "6MonthGIftCount" (
"ConstituentID"
,"GiftCount"
)
AS (
SELECT COUNT(DISTINCT "GiftView"."GiftID" FROM "GiftView" WHERE MONTHS_BETWEEN("GiftView"."GiftDate", getdate()) <= 6 GROUP BY "GiftView"."ConstituentID")
SELECT...CASE
WHEN "6MonthGiftCount"."GiftCount" >= 4
THEN 'A010'
)
Perform your grouping/COUNT(1) in a subquery to obtain the total # of donations by ConstituentID, then JOIN this total into your main query that uses this new column to perform its CASE statement.
select
hist.*,
case when timesDonated > 5 then 'gracious donor'
when timesDonated > 3 then 'repeated donor'
when timesDonated >= 1 then 'donor'
else null end as donorCode
from gifthistory hist
left join ( /* your grouping subquery here, pretending to be a new table */
select
personID,
count(1) as timesDonated
from gifthistory i
WHERE abs(months_between(giftDate, sysdate)) <= 6
group by personid ) grp on hist.personid = grp.personID
order by 1;
*Naturally, syntax changes will vary by DB; you didn't specify which it was based on, but you should be able to use this template with whichever you utilize. This works in both Oracle and SQL Server after tweaking the month calculation appropriately.

SQL INNER JOIN tables with different row names

Thank you for taking the time to read this, it is probably a very basic question. Most search queries I did seemed a bit more in depth to the INNER JOIN operator.
Basically my question is this: I have a shipping and receiving table with dates on when the item was either shipped or received. In the shipping table (tbl_shipping) the date row is labeled as trans_out_date and for the receiving table (tbl_receiving) the date row is labeled as trans_in_date.
I can view transactions set on either table from a user entered form but I want to populate a table with information pulled from both tables where the criteria meets. ie. If the receiving table has 10 transactions done in April and 5 in June and the shipping table has 15 transactions in April and 10 in June... when the user wants to see all transactions in June, it will populate the 15 transactions that occurred in June.
As of right now, I can pull only from 1 table with
SELECT *
FROM tbl_shipping
WHERE trans_out_date >= ‘from_date’
AND trans_out_date <= ‘to_date’
Would this be the appropriate syntax for what I am looking to achieve?
SELECT *
FROM tbl_shipping
INNER JOIN tbl_receiving ON tbl_shipping.trans_out_date = tbl_receiving.trans_in_date
WHERE
tbl_shipping.trans_out_date >= ‘from_date’
AND tbl_shipping.trans_out_date <= ‘to_date’
Thank you again in advance for reading this.
You appear to want union all rather than a join:
SELECT s.item, s.trans_out_date as dte, 'shipped' as which
FROM tbl_shipping S
WHERE s.trans_out_date >= ? AND
s.trans_out_date <= ?
UNION ALL
SELECT r.item, NULL, r.trans_in_date as dte, 'received'
FROM tbl_receiving r
WHERE r.trans_out_date >= ? AND
r.trans_out_date <= ?
ORDER BY dte;
Notes:
A JOIN can cause problems due to data that goes missing (because dates don't line up) or data that gets duplicated (because there are multiple dates).
The ? is for a parameter. If you are calling this from an application, use parameters!
You can include additional columns for more information in the result set.
This may not be the exact result format you want. If not, ask another question with sample data and desired results.

Can't access CTE via inner join SQL Server

I know I'm missing something obvious but it's not so obvious to me!
I've got a table valued function that produces a nice interval range of dates given a start, end, interval (thanks to another SO answer!).
I've another TVF that produces the latest part transaction given a date.
However, I was after being able to produce the last parts transaction in a series of dates lying between the start and end dates given. So, given March to May and an interval of say, 2 days, I'd get a sort of time series between the two.
However, I've hit a wall now with CTE's and was trying to avoid going into procedural/cursor style looping to do this.
This is the code:
WITH datesTbl(DateValue)
AS (SELECT DateValue
FROM [dbo].[DateRange]('2016-03-18', '2016-04-27', 1))
SELECT *
FROM datesTbl dr
INNER JOIN dbo.MoveDateDiff(dr.Datevalue, DATEADD(day, 1, dr.DateValue), 14792) pm
ON DATEDIFF(Day, dr.dateValue, pm.MovementDate) <= 1;
I know I've other conceptual errors in the underlying TVF's however here I'm wanting to find a way past the fact I can't seem to access the CTE in the first part of the Inner Join statement (there is no syntax error after the ON declaration!).
Any guidance would be gratefully received!
When you use a TVF, you want APPLY, not JOIN:
WITH datesTbl(DateValue) as (
SELECT DateValue
FROM [dbo].[DateRange]('2016-03-18', '2016-04-27', 1)
)
SELECT *
FROM datesTbl dr CROSS APPLY
dbo.MoveDateDiff(dr.Datevalue, DATEADD(day, 1, dr.DateValue), 14792) pm
WHERE DATEDIFF(Day, dr.dateValue, pm.MovementDate) <= 1;

SQL- get dates that were used in the WHERE clause?

We have a ERP that integrates nicely with Crystal Reports.
Now, we can add filters through this application, and it passes these to the report (not as parameters but somehow adds this to the WHERE clause).
The problem is, when filtering dates, we have no way in the report to determine what date range the user selected (as we want to show this date on the report).
Any idea how I can show this through SQL?
I was thinking of using the dual table, and selecting a huge list of dates, then using the MIN and MAX of these dates to determine which was selected. The problem is, I can't join this onto my original query without adding LOTS of rows.
I have this so far:
SELECT
MIN(DTE) MIN_DTE,
MAX(DTE) MAX_DTE
FROM
(
SELECT
TRUNC(SYSDATE)-(5*365) + ROWNUM AS DTE
FROM
DUAL
CONNECT BY
ROWNUM <= (10*365)
)
WHERE
DTE >= '12-NOV-07'
AND DTE <= '12-DEC-07'
But the problem is I can't work out how to join that to my original query without upsetting the row cont.
Any other ideas?
That query returns only one row, so it won't upset the row count at all, unless there is something else going on (like, maybe, the automatic filtering doesn't work in subqueries).
Otherwise, this should work as expected:
SELECT q.*, max_min.*
FROM ( ... put your original query here ...) q,
( ... put the subquery that returns one row with max & min here ...) max_min
That's all to it.