I have simple mysql query:
SELECT product.user_id, product.type, product.body, product.created, product.id, product.url, product.name, product.price, images.src
FROM xn_product AS product
LEFT JOIN xn_images AS images ON product.id = images.item_id
WHERE product.active = '1' AND images.type = 'product' AND product.promoted = '1' AND images.main = '1' AND product.url = '". $url "'
And I have problem. When in images.table dont't have product.id query is not executed. I tried to do something with IF and IF NULL but without success.
I want to see if it is empty images.src to overwrite them as 'empty.jpg' OR 1
Try using an INNER join
SELECT product.user_id, product.type, product.body, product.created, product.id, product.url, product.name, product.price, images.src
FROM xn_product AS product
INNER JOIN xn_images AS images ON product.id = images.item_id
WHERE product.active = '1' AND images.type = 'product' AND product.promoted = '1' AND images.main = '1' AND product.url = '". $url ."'
Related
Sorry for my English.
I ran into a mistake with EF Core 5.0.9 when is use Filtered Include and Select in same time and i don't know is a bug or feature. :)
return await _dbContext.User
.Where(u => !u.TOROLT)
.Where(u => ids.Contains(u.Id))
.Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.Select(u => new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = u.EventUsers.First().Id,
IsCelebrated = u.EventUsers.First().IsCelebrated,
IsEventAdmin = u.EventUsers.First().IsEventAdmin,
IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
IsInvited = u.EventUsers.First().IsInvited,
})
.ToListAsync();
In this time the first elements is select is not from filtered include just from a normal include. SQL Script from Profiler:
SELECT
[u].[Id],
[u].[FirstName],
[u].[LastName],
(
SELECT TOP(1) [e].[Id]
FROM [dbo].[EventUser] AS [e]
WHERE [u].[Id] = [e].[UserId]) AS [EventUserId],
(
SELECT TOP(1) [e0].[IsCelebrated]
FROM [dbo].[EventUser] AS [e0]
WHERE [u].[Id] = [e0].[UserId]) AS [IsCelebrated],
(
SELECT TOP(1) [e1].[IsEventAdmin]
FROM [dbo].[EventUser] AS [e1]
WHERE [u].[Id] = [e1].[UserId]) AS [IsEventAdmin],
(
SELECT TOP(1) [e2].[IsInviteAccepted]
FROM [dbo].[EventUser] AS [e2]
WHERE [u].[Id] = [e2].[UserId]) AS [IsInviteAccepted],
(
SELECT TOP(1) [e3].[IsInvited]
FROM [dbo].[EventUser] AS [e3]
WHERE [u].[Id] = [e3].[UserId]) AS [IsInvited]
FROM [dbo].[User] AS [u]
WHERE ([u].[TOROLT] <> CAST(1 AS bit))
AND [u].[Id] IN (2, 1, 3, 4, 5)
But if is separate filtered include and select, than it work's fine, but this select complete record and not the part of him from database:
var a = await _dbContext.User
.Where(u => !u.TOROLT)
.Where(u => ids.Contains(u.Id))
.Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.ToListAsync();
return a.Select(u => new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = u.EventUsers.First().Id,
IsCelebrated = u.EventUsers.First().IsCelebrated,
IsEventAdmin = u.EventUsers.First().IsEventAdmin,
IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
IsInvited = u.EventUsers.First().IsInvited,
})
.ToList();
Any idea why is this, and how can i solve solve this?
THX
Include is completely ignored if you have custom projection Select, so your filter will be also ignored. It is not a bug, Include works only when you get whole entity from query.
Anyway consider to rewrite your query:
var query =
from u in _dbContext.User
where !u.TOROLT && ids.Contains(u.Id)
from eu in u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId)
.Take(1)
.DefaultIfEmpty()
select new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = eu.Id,
IsCelebrated = eu.IsCelebrated,
IsEventAdmin = eu.IsEventAdmin,
IsInviteAccepted = eu.IsInviteAccepted,
IsInvited = eu.IsInvited,
};
var result = await query.ToListAsync();
I have this query:
WITH grouped_messages AS
(SELECT
um.conversation_id,
array_agg(json_build_object('message', um.message, 'sent_at', um.created_at))
FROM user_messages um
INNER JOIN users_conversations c ON c.conversation_id = um.conversation_id
WHERE c.user_id = '#{user_id}' AND um.user_id != '#{user_id}' #{ "and um.created_at >= '#{timestamp}'" IF TIMESTAMP}
GROUP BY um.conversation_id
),
senders AS
(SELECT
gm.conversation_id,
json_build_object('id', u.id, 'user_name', u.user_name, 'avatar',
('https://my-staging.s3.amazonaws.com/public/uploads/user/' || u.id :: TEXT ||
'/avatar.jpg')) AS sender
FROM grouped_messages AS gm
INNER JOIN users_conversations c ON c.conversation_id = gm.conversation_id
INNER JOIN users u ON u.id = c.user_id
WHERE u.id != '#{user_id}'
)
SELECT json_object_agg(grouped_messages.conversation_id,
json_build_object('new_messages', grouped_messages.array_agg, 'sender', senders.sender))
FROM grouped_messages
INNER JOIN senders ON senders.conversation_id = grouped_messages.conversation_id
Which outputs, for example:
{
"62": {
"new_messages": [
{
"message": "some",
"sent_at": "2016-05-30T20:19:53.786024"
},
{
"message": null,
"sent_at": "2016-05-30T20:19:26.408814"
}
],
"sender": {
"id": "e4ba308b-a5cf-47ad-b8d6-d774eb325411",
"user_name": null,
"avatar": "https://my-staging.s3.amazonaws.com/public/uploads/user/e4ba308b-a5cf-47ad-b8d6-d774eb325411/avatar.jpg"
}
}
}
Now, what I need is to have a conditional statement in this query.
If u (user) avatar is not NULL then apply this 'https://my-staging.s3.amazonaws.com/public/uploads/user/' || u.id::text || '/avatar.jpg', otherwise just insert ':null' string (so that any JSON parser recognizes it as a null object).
Not sure how to put this if-else here in select statement and also how to ensure that part about JSON parser.
worked for me:
(SELECT gm.conversation_id, json_build_object('id', u.id, 'user_name', u.user_name,
'avatar', (
CASE WHEN u.avatar IS NULL THEN ':null'
ELSE ('https://my-staging.s3.amazonaws.com/public/uploads/user/' || u.id::text || '/avatar.jpg')
END))
You can provide case-statement in SELECT block as if it were value (with optional AS).
This is a good use of the CASE expression. In this scenario, you want to return either a hard URL to their avatar if the avatar field is not null, and NULL otherwise.
This is accomplished thus (omitting the other portions of the query for readability):
json_build_object('id', u.id, 'user_name', u.user_name,
'avatar',
CASE WHEN u.avatar IS NULL
THEN NULL
ELSE
(
'https://my-staging.s3.amazonaws.com/public/uploads/user/'
|| u.id :: TEXT ||
'/avatar.jpg') END) AS sender
I have an working MySQL Query now i need it to convert to Typo3 Syntax
SELECT
tt_news_tx_extendnews_subscriber_mm.uid_local,
fe_users.*
FROM fe_users
JOIN tt_news_tx_extendnews_subscriber_mm
ON tt_news_tx_extendnews_subscriber_mm.uid_foreign = fe_users.uid
WHERE tt_news_tx_extendnews_subscriber_mm.uid_local = 101
TYPO3
$res0 = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
'tt_news_tx_extendnews_subscriber_mm.uid_local,fe_users.*',
'fe_users',
'tt_news_tx_extendnews_subscriber_mm',
'tt_news_tx_extendnews_subscriber_mm.uid_foreign = fe_users.uid',
'tt_news_tx_extendnews_subscriber_mm.uid_local = 101',
'',
'',
''
);
the result is empty...anybody knows how this work with typo3?
Debug brings this: $GLOBALS['TYPO3_DB']->debug_lastBuiltQuery;
SELECT tt_news_tx_extendnews_subscriber_mm.uid_local,fe_users.*
FROM fe_users,tt_news_tx_extendnews_subscriber_mm,tt_news_tx_extendnews_subscriber_mm.uid_foreign = fe_users.uid
WHERE fe_users.uid=tt_news_tx_extendnews_subscriber_mm.uid_local
AND tt_news_tx_extendnews_subscriber_mm.uid_foreign = fe_users.uid.uid=tt_news_tx_extendnews_subscriber_mm.uid_foreign tt_news_tx_extendnews_subscriber_mm.uid_local = 101
By exec_SELECT_mm_query the 4th parameter is the foreign key table name, not the reference. You need instead of:
tt_news_tx_extendnews_subscriber_mm.uid_foreign = fe_users.uid
only:
fe_users
See more details in TYPO3 api : exec_SELECT_mm_query.
I think, you can try the following:
$res0 = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
'tt_news_tx_extendnews_subscriber_mm.uid_local,fe_users.*',
'tt_news',
'tt_news_tx_extendnews_subscriber_mm',
'fe_users',
'tt_news_tx_extendnews_subscriber_mm.uid_local = 101',
'',
'',
''
);
Or you can use exactly the SQL what you have with the following little trick, because exe_SELECTquery only concats your string to SELECT..., FROM... (and so on...) parts. So because of this, you can use a JOIN in FROM part.
$res0 = $GLOBALS['TYPO3_DB']->exec_SELECTquery('tt_news_tx_extendnews_subscriber_mm.uid_local,fe_users.*',
'fe_users
JOIN tt_news_tx_extendnews_subscriber_mm
ON tt_news_tx_extendnews_subscriber_mm.uid_foreign = fe_users.uid',
'tt_news_tx_extendnews_subscriber_mm.uid_local = 101',
'',
'',
'');
I'm getting an error with a query, my question is: can i chain joins?
My first join is to the primary table, but my second join is to the table joined to the primary table. This is the query:
$query = $this->getDbTable()->select()
->from(array('ca' => 'contracts_allotment'),
array('id',
'contracts_rooms_id' => new Zend_Db_Expr("CONCAT(room_type_desc, '-', room_characteristics_desc)")
))
->join(array('cr' => 'contracts_rooms'),
'ca.contract_rooms_id = cr.id',
array())
->join(array('rt' => 'room_types'),
'cr.room_id = rt.id',
array('room_type_desc'))
->join(array('rc' => 'room_characteristics'),
'cr.char_id = rc.id',
array('room_characteristics_desc'))
->where('contract_id = ?', $contractId);
var_dump($this->getDbTable()->fetchAll($query));die;
I'm getting:
Select query cannot join with another table"
The error comes from Zend/Db/Table/Select::assemble()
Here you have some inside assemble():
// Check each column to ensure it only references the primary table
if ($column) {
if (!isset($from[$table]) || $from[$table]['tableName'] != $primary) {
var_dump($from[$table]['tableName'], $primary);die;
require_once 'Zend/Db/Table/Select/Exception.php';
throw new Zend_Db_Table_Select_Exception('Select query cannot join with another table');
}
}
The var_dump() prints:
string(10) "room_types" string(19) "contracts_allotment"
Any idea?
Don't forget to lock the tables when doing joins:
$query = $this->getDbTable()->select()
->setIntegrityCheck(false)
->from(array('ca' => 'contracts_allotment'),
array('id',
'contracts_rooms_id' => new Zend_Db_Expr("CONCAT(room_type_desc, '-', room_characteristics_desc)")
))
->join(array('cr' => 'contracts_rooms'),
'ca.contract_rooms_id = cr.id',
array())
->join(array('rt' => 'room_types'),
'cr.room_id = rt.id',
array('room_type_desc'))
->join(array('rc' => 'room_characteristics'),
'cr.char_id = rc.id',
array('room_characteristics_desc'))
->where('contract_id = ?', $contractId);
->setIntegrityCheck(false) should at least get you a new error.
I cannot rewrite the current DB schema right now BTW, but that's beside the point to the issue I've hit, so please ignore the table structure :D
I'm running this DB query:
my $rs = $dbx->resultset('Result')->search(
{
'result_hnd' => 16078055,
'seasons.outdoor' => 'venue.outdoors',
'seasons.start_date' => { '<=' => 'meet.date_end' },
'seasons.end_date' => { '>=' => 'meet.date_begin' },
},
{
'join' => [
{
'team' => {
'league_teams' => {
'league' => 'seasons',
},
},
},
{
'meet' => 'venue'
},
],
'+select' => ['seasons.season_hnd','seasons.name','seasons.start_date','seasons.end_date','meet.date_begin','meet.date_end'],
'+as' => ['season_hnd','season_name','s_start','s_end','m_start','m_end'],
columns => ['result_hnd'],
group_by => ['seasons.season_hnd'],
}
);
When I run this, I get no results. With DBIC_TRACE on, I see the generated SQL as:
SELECT me.result_hnd, seasons.season_hnd, seasons.name, seasons.start_date, seasons.end_date, meet.date_begin, meet.date_end FROM track.result me JOIN track.team team ON team.team_hnd = me.team_hnd LEFT JOIN track.league_team league_teams ON league_teams.team_hnd = team.team_hnd LEFT JOIN track.league league ON league.league_hnd = league_teams.league_hnd LEFT JOIN track.season seasons ON seasons.league_hnd = league.league_hnd OR seasons.league_hnd = league.parent_league_hnd JOIN track.meet meet ON meet.meet_hnd = me.meet_hnd JOIN track.venue venue ON venue.venue_hnd = meet.venue_hnd WHERE ( ( result_hnd = ? AND seasons.end_date >= ? AND seasons.outdoor = ? AND seasons.start_date <= ? ) ) GROUP BY seasons.season_hnd: '16078055', 'meet.date_begin', 'venue.outdoors', 'meet.date_end'
When I copy and paste this statement into my MYSQL client (and interpolate the placeholders), like this:
SELECT me.result_hnd, seasons.season_hnd, seasons.name, seasons.start_date, seasons.end_date, meet.date_begin, meet.date_end
FROM track.result me
JOIN track.team team ON team.team_hnd = me.team_hnd
LEFT JOIN track.league_team league_teams ON league_teams.team_hnd = team.team_hnd
LEFT JOIN track.league league ON league.league_hnd = league_teams.league_hnd
LEFT JOIN track.season seasons ON seasons.league_hnd = league.league_hnd OR seasons.league_hnd = league.parent_league_hnd
JOIN track.meet meet ON meet.meet_hnd = me.meet_hnd
JOIN track.venue venue ON venue.venue_hnd = meet.venue_hnd
WHERE ( ( result_hnd = 16078055 AND seasons.end_date >= meet.date_begin AND seasons.outdoor = venue.outdoors AND seasons.start_date <= meet.date_end ) )
GROUP BY season_hnd;
I get the exact result I expect (7 records).
This is really bizarre. To all intents and purposes, isn't that exactly the same query? Am I missing something in my debugging? Or is something else happening at the DBIx::Class::ResultSet layer that isn't being dumped?
To tell SQL::Abstract that the value on the right is actually an identifier, you can do the following (as outlined in the docs):
{
'result_hnd' => 16078055,
'seasons.outdoor' => { -ident => 'venue.outdoors' },
'seasons.start_date' => { '<=' => { -ident => 'meet.date_end' } },
'seasons.end_date' => { '>=' => { -ident => 'meet.date_begin' } },
},
To all intents and purposes, isn't that exactly the same query?
(For all intents and purposes, ...)
No. In the log, you have something equivalent to
result_hnd = '16078055'
AND seasons.end_date >= 'meet.date_begin'
AND seasons.outdoor = 'venue.outdoors'
AND seasons.start_date <= 'meet.date_end'
or maybe
result_hnd = 16078055
AND seasons.end_date >= 'meet.date_begin'
AND seasons.outdoor = 'venue.outdoors'
AND seasons.start_date <= 'meet.date_end'
In your attempt, you used
result_hnd = 16078055
AND seasons.end_date >= meet.date_begin
AND seasons.outdoor = venue.outdoors
AND seasons.start_date <= meet.date_end
Sorry, I don't have the solution for you.