using doctrine and querybuilder, between two date - symfony

I want to retrieve some data using queryBuilder, the condition is to use a datetime field on parent table and pass it to where condition, the child table have two date start and end, the whole condition is to select parent row depend on date between the two date in child table
the code is:
$qb->select('parent,child')
->from($this->class, 'parent')
->innerJoin('parent.childTable', 'child')
//other join
// and where
//CONDITION -> startdate <= $date AND enddate >= $date
$betweenDates = $qb->expr()->andX(
$qb->expr()->gt("child.dateStart", "parent.datetime"),
$qb->expr()->lt("child.dateEnd", "parent.datetime")
);
//CONDITION 4 -> enddate == NULL
$endDateNull = $qb->expr()->isNull( 'child.dateEnd');
$dates = $qb->expr()->orX($betweenDates, $endDateNull);
// take care of dateEnd if it's null
$qb->expr()->andX($dates);
the problem is the where condition not work and the select still give me childs not respect date condition
any help would be greatly appreciated.

Related

SQL: Sum based on specified dates

Thanks again for the help everyone. I went with the script below...
SELECT beginning, end,
(SELECT SUM(sale) FROM sales_log WHERE date BETWEEN beginning AND `end` ) AS sales
FROM performance
and I added a salesperson column to both the performance table and sales_log but it winds up crashing DB Browser. What is the issue here? New code below:
SELECT beginning, end, salesperson
(SELECT SUM(sale) FROM sales_log WHERE (date BETWEEN beginning AND end) AND sales_log.salesperson = performance.salesperson ) AS sales
FROM performance
I believe that the following may do what you wish or be the basis for what you wish.
WITH sales_log_cte AS
(
SELECT substr(date,(length(date) -3),4)||'-'||
CASE WHEN length(replace(substr(date,instr(date,'/')+1,2),'/','')) < 2 THEN '0' ELSE '' END
||replace(substr(date,instr(date,'/')+1,2),'/','')||'-'||
CASE WHEN length(substr(date,1,instr(date,'/') -1)) < 2 THEN '0' ELSE '' END||substr(date,1,instr(date,'/') -1) AS date,
CAST(sale AS REAL) AS sale
FROM sales_log
),
performance_cte AS
(
SELECT substr(beginning,(length(beginning) -3),4)||'-'||
CASE WHEN length(replace(substr(beginning,instr(beginning,'/')+1,2),'/','')) < 2 THEN '0' ELSE '' END
||replace(substr(beginning,instr(beginning,'/')+1,2),'/','')||'-'||
CASE WHEN length(substr(beginning,1,instr(beginning,'/') -1)) < 2 THEN '0' ELSE '' END||substr(beginning,1,instr(beginning,'/') -1)
AS beginning,
substr(`end`,(length(`end`) -3),4)||'-'||
CASE WHEN length(replace(substr(`end`,instr(`end`,'/')+1,2),'/','')) < 2 THEN '0' ELSE '' END
||replace(substr(`end`,instr(`end`,'/')+1,2),'/','')||'-'||
CASE WHEN length(substr(`end`,1,instr(`end`,'/') -1)) < 2 THEN '0' ELSE '' END||substr(`end`,1,instr(`end`,'/') -1)
AS `end`
FROM performance
)
SELECT beginning, `end` , (SELECT SUM(sale) FROM sales_log_cte WHERE date BETWEEN beginning AND `end` ) AS sales
FROM performance_cte
;
From your data this results in :-
As can be seen the bulk of the code is converting the dates into a format (i.e. YYYY-MM-DD) that is usable/recognisable by SQLite for the BETWEEN clause.
Date And Time Functions
I don't believe that you want a join between performance (preformance_cte after reformatting the dates) and sales_log (sales_log_cte) as this will be a cartesian product and then sum will sum all the results within the range.
The use of end as a column name is also awkward as it is a KEYWORD requiring it to be enclosed (` grave accents used in the above).
The above works by using 2 CTE's (Common Table Expresssions), which are temporary tables who'd life time is for the query in which they are used.
The first sales_log_cte is simply the sales_log table but with the date reformatted. The second, likewise, is simply the performace table with the dates reformatted.
If the tables already has suitable date formatting then all of the above could simply be :-
SELECT beginning, `end` , (SELECT SUM(sale) FROM sales_log WHERE date BETWEEN beginning AND `end` ) AS sales FROM performance;

Extbase-DISTINCT Values from repository

Fetch unique room numbers from my database.
My table is tx_example_domain_model_room which has columns startdatetime, enddatetime and roomKey. I want to fetch roomKey greater than given datetime. When I query, the results returns all the roomKey that are greater than given datetime, all the roomKey having more than the given datetime comes up. However, its not distinct. I want to get the distinct rooms. Below is my code:
List.html List
f:form.select options="{roomKeys}" optionLabelField="roomKey"
Could you let me know how to get distinct values. One more detail: Room is a model that contains the attributes roomKey, startdatetime and enddatatime.
Controller
$roomKey = $this->roomRepository->RoomKeyFetcher($enddatetime, $startdatetime);
var_dump($roomKey);
$unique_rooms = array_unique($roomKey);
$this->view->assign('roomKeys', $unique_rooms);
Repository:
public function RoomKey($enddatetime, $startdatetime) {
$query = $this->createQuery();
$query->statement('SELECT * FROM tx_example_domain_model_room
WHERE startdatetime >= ? OR enddatetime <= ?',
[$enddatetime, $startdatetime]);
$results = $query->execute();
return $results;
}
Just using DISTINCT keyword on roomkey should do it.
$query->statement('SELECT DISTINCT roomKey FROM tx_example_domain_model_room
WHERE startdatetime >= ? OR enddatetime <= ?',
[$enddatetime, $startdatetime]);

Oracle - Connect By Clause Required in query block

I would like to utilize the Month Column in the below syntax in a Case Statement. When I create a sub query I receive the Oracle error 01788 Connect By Clause Required in query block. How can one utilize the Month column in the case statment in the subquery?
TO_CHAR(ADD_MONTHS(TRUNC(StartDate, 'MM'), LEVEL - 1), 'YYYYMM') AS Month
Query below:
SELECT
CASE
WHEN first_assgn_dt_YYYYMM <= Month
THEN 0
WHEN EndDate < LAST_DAY(EndDate) AND EndDate != sysdate
AND LEVEL = 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'),TRUNC(StartDate,'MM'))
THEN 0
ELSE 1
END AS active_at_month_end
FROM (
WITH
ActiveMemberData (ID,StartDate,EndDate,first_assgn_dt,first_assgn_dt_YYYYMM) AS (
SELECT DISTINCT
x.ID,
TRUNC(x.start_dt) AS StartDate,
CASE WHEN TRUNC(X.END_DT) = '1-JAN-3000' THEN SYSDATE ELSE TO_DATE(X.END_DT) END AS EndDate,
x.first_assgn_dt,
TO_CHAR(first_assgn_dt,'YYYYMM') AS first_assgn_dt_YYYYMM
FROM X
LEFT JOIN D ON X.MID = D.ID
WHERE 1=1
)
--------------------------------------------------
SELECT DISTINCT
ID,
first_assgn_dt,
first_assgn_dt_YYYYMM,
StartDate,
TO_CHAR(StartDate,'YYYYMM') AS StartDate_YYYYMM,
EndDate,
TO_CHAR(ADD_MONTHS(TRUNC(StartDate, 'MM'), LEVEL - 1), 'YYYYMM') AS Month,
LAST_DAY(EndDate) AS LastDayOfMonth
FROM ActiveMemberData
WHERE 1=1
------------------------------------------------------------------------------------
CONNECT BY LEVEL <= 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'), TRUNC(StartDate,'MM'))
AND PRIOR ID = ID AND PRIOR STARTDATE = STARTDATE
AND PRIOR sys_guid() IS NOT NULL
) Z
WHERE 1=1
ORDER BY
ID,
Month
That has nothing to do with trying to refer to Month from the inline view; that is fine. It's the separate reference to level that is causing the error.
If you want to be able to see the level from your inline view in the outer query, as you are with this line:
AND LEVEL = 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'),TRUNC(StartDate,'MM'))
then you have to include it in the select list - with an alias - and then refer to that alias:
SELECT
CASE
...
AND LEVEL_ALIAS = 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'),TRUNC(StartDate,'MM'))
...
FROM (
...
SELECT DISTINCT
LEVEL as LEVEL_ALIAS,
ID,
...
You can call the alias whatever you want, of course; you just can't use the reserved word level.
Anything you want visible in the outer query always has to be in the inline view's select list - but usually you can keep the original column name; you have to use an alias for an expression or a pseucocolumn though, which is the case here.
You don't have to use an alias for the reserved word. Just add double quotes and capitilise it i.e. "LEVEL"

A trigger to calculate hour difference between two DateTime fields

3 fields in a Table : START_DATE, END_DATE , DIFF. All three are DATETIME fields. I would like a trigger (AFTER UPDATE) to calculate the time difference between the START_DATE and END_DATE values in the DIFF field. I would like the result to be like : 01 Day - 12 Hours - 15 Min. How can I achieve this ? I would like to know also how it is done i.e the way to show the hour difference so that DIFF would display something like 27:15:00.
This seems to work:
CREATE TRIGGER [DIFF]
AFTER UPDATE OF [end_date]
ON [Table1]
BEGIN
UPDATE Table1 SET DIFF =
cast(
(
strftime('%s',Table1.end_date)-strftime('%s',Table1.start_date)
) AS INT
) / 60/60 ;
END
As far as I can tell, this works ok:
CREATE TRIGGER [TIME_DIFFERENCE]
AFTER UPDATE OF [end_date]
ON [Table1]
BEGIN
UPDATE Table1 SET DIFF =
cast(
(
strftime('%s',Table1.end_date)-strftime('%s',Table1.start_date)
) AS INT
) / 60/60 ;
END

SQL retrieving data NOT IN

SELECT ID, Name
FROM dbo.AmenitiesList
WHERE TypeID=#Type and Status = 'Available'
AND ID NOT IN
(SELECT AmenitiesID FROM dbo.ReservationList
WHERE Status = 'Cancelled' AND StartDate between #Arrival and #Departure
or EndDate between #Arrival and #Departure
or #Arrival between StartDate and EndDate
or #Departure between StartDate and EndDate)
This is my query, I want to display all the Available Amenities that the status is 'Cancelled' and the Arrival Date and Departure date is not between in the ArrivalDate and Departure date in Database. But when retrieving data, I didn't get the Amenities available because when the Status is cancelled it triggers the other condition about those in between dates. How to Avoid that?
I want to display Amenities that is Cancelled and also not between ArrivalDate and Departure Date
Thank you in advance guys!
For performance and optimization, consider table variables.
DECLARE #TABLE AS TABLE
(
AmenityID INT PRIMARY KEY CLUSTERED
)
INSERT INTO #TABLE
SELECT AmenitiesID FROM dbo.ReservationList
--Your conditions
--Get values that exist
SELECT * FROM AmentitiesList al
INNER JOIN #Table t on al.AmenityID = t.AmenityID
--Get values that don't
SELECT * FROM AmentitiesList al
LEFT JOIN #Table t on al.AmenityID = t.AmenityID
WHERE t.AmenityID IS NULL
Just because code is shorter, doesn't mean it scales. Left Joins are also a pain...
You could easily get rid of that too by using a table variable.
DECLARE #AmenityList AS TABLE
(
AmenityID INT PRIMARY KEY CLUSTERED
Matched BIT DEFAULT(0)
)
INSERT INTO #AmenityList
Select AmenityID FROM AmentitiesList
UPDATE #AmenityList SET Matched = 1
FROM #AmenitityList al
INNER JOIN #Table t on t.AmentityID = al.AmentityID
SELECT * FROM #AmentityList WHERE Matched = 0
How about this version?
SELECT ID, Name
FROM dbo.AmenitiesList
WHERE TypeID=#Type and Status = 'Available'
AND ID NOT IN
(SELECT AmenitiesID FROM dbo.ReservationList
WHERE Status = 'Cancelled' AND (StartDate between #Arrival and #Departure
or EndDate between #Arrival and #Departure
or #Arrival between StartDate and EndDate
or #Departure between StartDate and EndDate))
SELECT ID, Name
FROM dbo.AmenitiesList
WHERE TypeID=#Type and Status = 'Available'
AND ID NOT IN
(SELECT AmenitiesID FROM dbo.ReservationList
WHERE Status != 'Cancelled' AND Status != 'Check Out' AND ((#Arrival <= EndDate) AND (#Departure >= StartDate)))
This solve my problem! By the way thank you guys for spending time giving information to me! God Bless!

Resources