How to pass subquery as table name to another query in yii2 - yii

I have a query which I am trying to convert into yii2 syntax. Below is the query
SELECT project_id, user_ref_id FROM
(
SELECT `project_id`, `user_ref_id`
FROM `projectsList`
WHERE user_type_ref_id = 1) AS a WHERE user_ref_id = '.yii::$app->user->id;
I am trying to convert it into yii2 format like
$subQuery = (new Query())->select(['p.project_id', 'p.user_ref_id'])->from('projectsList')->where(['user_type_ref_id' => 1]);
$uQuery = (new Query())->select(['p.project_id', 'p.user_ref_id'])->from($subQuery)->where(['user_ref_id ' => yii::$app->user->id])->all();
It is giving an error like
trim() expects parameter 1 to be string, object given
How to I pass subquery as table name to another query

Not tested, but generally this is how it goes. You need to pass the subQuery as a table. So change ->from($subQuery) in the second query to ->from(['subQuery' => $subQuery])
$subQuery = (new Query())->select(['p.project_id', 'p.user_ref_id'])->from('projectsList')->where(['user_type_ref_id' => 1]);
Then
$query = (new Query())->select(['p.project_id', 'p.user_ref_id'])->from(['subQuery' => $subQuery])->where(['subQuery.user_ref_id ' => yii::$app->user->id])->all();

Related

ASP MVC Linq Query

I have a query like this
var errorLogs = db.ErrorLogs.Include(e => e.Inventory);
return View(await errorLogs.ToListAsync());
The Inventory Contain a field named CreatedBy
I want to add a where clause on this field how can I do it?
If it is on the Inventory table, then it should be something like the following
var errorLogs = db.ErrorLogs.Include(e => e.Inventory).Where(el => el.Inventory.CreatedBy == "Sanjoy");

sql "not in" in Linq using datatable

How to convert sql query to linq using datatable.
select DISTINCT targeturl from internal where TargetURL NOT in (select DISTINCT url from Internal)
using this query, but still not getting the correct result.
var List1 = dt.AsEnumerable().Select(c => c.Field<string>("URL")).Distinct().ToList();
var List2 = dt.AsEnumerable().Select(c => c.Field<string>("TargetURL")).Distinct().ToList();
var Targetname = List2.Except(List1.ToList()).ToList();
You can also try populating an object then using the object to populate the datatable.
var data = Select(c => c.Field<string>("TargetURL")).Distinct().ToList();
Datatable dtMyTable = new Datatable();
dtMytable.Columns.Add("col1",typeof(string));
dtMytable.Columns.Add("col2",typeof(string));
dtMytable.Columns.Add("col3",typeof(string));
then populate the table
foreach (var item in data)
{
dtMytable.Rows.Add(data.col1,data.col2,data.col3);
}
I prefer to separate
first
dim query = (from u in Internal select u.url).distinct
Second
dim tmp = (from t in Interal where not query.contains(TargetURL) select TargetURL ).ToList
It's in VB.net but You can translate easily
And you can too distinct with group by request.
To write SELECT DISTINCT targeturl from internal where TargetURL NOT in (select DISTINCT url from Internal) in a linq lambda expression, you could use the following:
var result = Internal
.Select(a => a.TargetURL)
.Where(a => !Internal.Select(i => i.url).Distinct().Contains(a.TargetURL));
Or break it out a little as:
var distinctUrls = Internal.Select(i => i.url).Distinct();
var result = Internal.Select(a => a.TargetUrl)
.Where(a => !disctinctUrls.Contains(a.TargetUrl));
The above creates an IEnumerable of urls, which we use as an exclusion in the where predicate.

Rails Arel equivalent of this complex sql query

Here is the original logic
(scrape_datas = ScrapeData.find(
:all, :conditions =>
"artist_status = 'NOT_FOUND'
AND blacklisted = 1
AND extracted = 0
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
I've been able to split up the first part better
scrape_datas = ScrapeData.where(
:artist_status => 'NOT_FOUND',
:blacklisted => 1,
:extracted => 0
)
Although having issues getting the "and not EXISTS" query into the mix
and not EXISTS(
SELECT * FROM artist_name_suggestions where original = artist_name
)
Thanks!
Firstly you can extract simple scopes:
scope :not_found, where(:artist_status => 'NOT_FOUND')
scope :blacklisted, where(:blacklisted => 1)
scope :extracted, where(:extracted => 0)
Then add a query method (assume artist_name is a column of scrape_datas):
def self.no_suggestions
scrape_datas = ScrapeData.arel_table
suggestions = ArtistNameSuggestion.arel_table
where(ArtistNameSuggestion.where(
suggestions[:original].eq(scrape_datas[:artist_name])
).exists.not)
end
Now you can do something like this:
ScrapeData.not_found.blacklisted.extracted.no_suggestions

Hard time counting records using CDbCriteria

When I try to use CDbCriteria to count records I get Active record "Hotels" is trying to select an invalid column "count(t.id) as count".
Here is my code:
$criteria = new CDbCriteria();
$criteria->select = 'count(t.id) as `count`, t.`keywords`, min(offers.first_bookin) as first_bookin';
$criteria->with = array('offers');
$criteria->group = 'offers.hotels_id';
$criteria->compare('first_bookin','>' . date('Y-m-d'));
$criteria->together = true;
$hotelItems = Hotels::model()->findAll($criteria);
And here are my relations defined in Hotels model:
return array(
'headers' => array(self::HAS_MANY, 'Headers', 'hotels_id'),
'offers' => array(self::HAS_MANY, 'Offers', 'hotels_id'),
);
I red a lot of posts here and on some other sites, but nothing seems to work. I tried with count(*), count(id), I tried splitting the select property into an array. Every time I get the same error.
Just remove the backticks from the alias and the count should work. Of course if you want to access the count easily you will have to declare it as a class variable, as mentioned by onkarjanwa.
If you check the source of the error, it's this function: getColumnSelect of CActiveFinder, the select for count should satisfy this line, in getColumnSelect:
elseif(preg_match('/^(.*?)\s+AS\s+(\w+)$/im',$name,$matches)) // if the column is already aliased
but because of the backticks in the alias name, it doesn't match, and it throws an error. So your select should be without the backticks for aliases:
$criteria->select = 'count(t.id) as count, t.`keywords`, min(offers.first_bookin) as first_bookin';
When i was testing this, i got another error in your compare, so you should change it to:
$criteria->compare('offers.first_bookin','>' . date('Y-m-d')); // can't use the alias in where clause
You need to declare a variable $count because Yii does not automatically initiate variables that are not table columns, so you can't use any new variable without declaring that.
You can solve your problem by doing this.
Declare a model variable:
class Hotels extends CActiveRecord
{
public $count;
....
}

NHibernate 3 - type safe way to select a distinct list of values

I am trying to select a distinct list of values from a table whilst ordering on another column.
The only thing working for me so far uses magic strings and an object array. Any better (type-safe) way?
var projectionList = Projections.ProjectionList();
projectionList.Add(Projections.Property("FolderName"));
projectionList.Add(Projections.Property("FolderOrder"));
var list = Session.QueryOver<T>()
.Where(d => d.Company.Id == SharePointContextHelper.Current.CurrentCompanyId)
.OrderBy(t => t.FolderOrder).Asc
.Select(Projections.Distinct(projectionList))
.List<object[]>()
.ToList();
return list.Select(l => new Folder((string)l[0])).ToList();
btw, doing it with linq won't work, you must select FolderOrder otherwise you'll get a sql error (ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
)
and then doing that gives a known error : Expression type 'NhDistinctExpression' is not supported by this SelectClauseVisitor. regarding using anonymous types with distinct
var q = Session.Query<T>()
.Where(d => d.Company.Id == SharePointContextHelper.Current.CurrentCompanyId)
.OrderBy(d => d.FolderOrder)
.Select(d => new {d.FolderName, d.FolderOrder})
.Distinct();
return q.ToList().Select(f => new Folder(f));
All seems a lot of hoops and complexity to do some sql basics....
To resolve the type-safety issue, the syntax is:
var projectionList = Projections.ProjectionList();
projectionList.Add(Projections.Property<T>(d => d.FolderName));
projectionList.Add(Projections.Property<T>(d => d.FolderOrder));
the object [] thing is unavoidable, unless you define a special class / struct to hold just FolderName and FolderOrder.
see this great introduction to QueryOver for type-saftey, which is most certainly supported.
best of luck.