Limit models to select - sql

I have a database table called Event which in CakePHP has its relationships coded to like so:
var $belongsTo = array('Sport');
var $hasOne = array('Result', 'Point', 'Writeup', 'Timetable', 'Photo');
Now am doing a query and only want to pull out Sport, Point, and Timetable
Which would result in me retrieving Sports, Events, Points, and Timetable.
Reason for not pulling everything is due the results having 17000+ rows.
Is there a way to only select those tables using:
$this->Event->find('all');
I have had a look at the API but can't see how its done.

You should set recursive to -1 in your app_model and only pull the things you require. never use recursive of 2 and http://book.cakephp.org/view/1323/Containable is awesome.
just $this->Event->find('all', array('contain' => array()));
if you do the trick of recursive as -1 in app_model, this is not needed, if would just be find('all') like you have

Related

How to modify value in column typeorm

I have 2 tables contractPoint and contractPointHistory
ContractPointHistory
ContractPoint
I would like to get contractPoint where point will be subtracted by pointChange. For example: ContractPoint -> id: 3, point: 5
ContractPointHistory has contractPointId: 3 and pointChange: -5. So after manipulating point in contractPoint should be 0
I wrote this code, but it works just for getRawMany(), not for getMany()
const contractPoints = await getRepository(ContractPoint).createQueryBuilder('contractPoint')
.addSelect('"contractPoint".point + COALESCE((SELECT SUM(cpHistory.point_change) FROM contract_point_history AS cpHistory WHERE cpHistory.contract_point_id = contractPoint.id), 0) AS points')
.andWhere('EXTRACT(YEAR FROM contractPoint.validFrom) = :year', { year })
.andWhere('contractPoint.contractId = :contractId', { contractId })
.orderBy('contractPoint.grantedAt', OrderByDirection.Desc)
.getMany();
The method getMany can be used to select all attributes of an entity. However, if one wants to select some specific attributes of an entity then one needs to use getRawMany.
As per the documentation -
There are two types of results you can get using select query builder:
entities or raw results. Most of the time, you need to select real
entities from your database, for example, users. For this purpose, you
use getOne and getMany. But sometimes you need to select some specific
data, let's say the sum of all user photos. This data is not an
entity, it's called raw data. To get raw data, you use getRawOne and
getRawMany
From this, we can conclude that the query which you want to generate can not be made using getMany method.

Laravel query builder for Charts.js

I have logic querying a MSSQL Server database view and I've been searching for a solutions along with trying different techniques. Of course I don't expect a full solution where this is two parts (query builder & frontend javascript/chart) but any helpful direction would greatly appreciated. Here I'm getting the count of Leads on a particular day grouped by the date created and source of the leads. I'm trying build this the Laravel way so to speak, and display in charts.js. I'm thinking I might need to make two different database calls/queries. One count and one for the group by source text.
Thank you for your help for a solutions or an helpful direction I can take.
I have already done total leads for another chart but this project has some extra sugar to it.
SELECT count([LeadID]) as numleads,[LeadSource],cast(leadcreated as date) as
`enter code here`createddate
FROM [myDatabase].[dbo].[viewAllLeads]
where companyid=001
group by cast(leadcreated as date),[LeadSource]
order by createddate
Chart.js set up:
- Top links (horizontal) the groupby info by LeadSource
- Left, y-axis - the count of the leads
- Bottom x-axis - the date lead was created
It should actually be straight forward, but you need to be aware that using DB::raw() is necessary. To begin with, here your query a little bit nicer formatted:
SELECT
[LeadSource],
CAST([leadcreated] as date) as createddate,
COUNT([LeadID]) as numleads
FROM [dbo].[viewAllLeads]
WHERE [companyid] = '001'
GROUP BY [LeadSource], CAST([leadcreated] as date)
ORDER BY [createddate]
And converted to an Eloquent query:
DB::table('viewAllLeads') // the query builder doesn't care if it's a table or view
->select([
'LeadSource',
DB::raw('CAST(leadcreated as date) as createddate'),
DB::raw('COUNT(LeadID) as numleads')
])
->where('companyid', '001')
->groupBy('LeadSource', DB::raw('CAST(leadcreated as date)'))
->orderBy('createddate')
->get();
This will return a Illuminate\Support\Collection containing stdClass objects of the following form:
object(stdClass)#1 (3) {
["LeadSource"] => string(3) "ABC"
["createddate"] => string(10) "2019-08-05"
["numleads"] => int(15)
}
$leads = Lead::where('companyid', $companyid)->get()->groupBy(function ($item) {
return $item->created_at->format('Y-m-d');
})->sortBy(function ($item) {
return $item->created_at->format('x');
});
if you use dd($leads) you can see the data structure.

Fusion of two queries in active record rails

How could these two queries be merged in Rails 5?
Event
.where(starts_at: date.beginning_of_day..date.end_of_day)
.where(kind: "opening")
Event.where("cast(strftime('%w', starts_at) as int) = ?", date.wday)
.where(kind: "opening")
.where(weekly_recurring: true)
I need to take all these events in one query for performance.
Thanks for the help
If you want to combine results then
Event.where(starts_at: date.beginning_of_day..date.end_of_day).where(kind: "opening").where("cast(strftime('%w', starts_at) as int) = ?", date.wday).where(kind: "opening").where(weekly_recurring: true)
If you want two separate results in one query, i dont think active records has such method.
I have always easier to write complex queries such as the one you need directly in SQL; It will be faster for you to write than trying to shoehorn it into ActiveRecord.
In your case, I would do something like this:
query = "starts_at between #{date.beginning_of_day} and #{date.end_of_day}
and kind = 'opening'
and weekly_recurring = true
and cast(strftime('%w', starts_at) as int) = #{date.wday}"
Event.where(query)
I find this approach easier and more maintanable.

Getting a count of a child relation and a count of a child of the child

Sorry for the naff title, but I'm not really sure how to explain this, I'm one of the new generation whose SQL skills have degraded thanks to the active record patterns!
Basically I have three tables in PostgreSQL
Client (One Client has many maps)
- id
Maps (Map has one client and many layers)
- id
- client_id
Layer (Layer has one map)
- id
- map_id
I would like to write an SQL query that returns Cliend.id along with a count of how many maps that client has and the total number of layers the client has across all maps.
Is this possible with a single query? Speed isn't of concern as this is just for analytical purposes so will be run infrequently.
I'd use a pair of subqueries for this. Something like:
SELECT
id,
(
SELECT count(map.id)
FROM map
WHERE map.client_id = client.id
) AS n_maps,
(
SELECT count(layer.id)
FROM map INNER JOIN layer ON (layer.map_id = map.id)
WHERE map.client_id = client.id
) AS n_layers
FROM client;
I'd do it like this, a single SQL Query inside a method in the Client model:
def self.statistics
Client.select("
clients.id AS client_id,
COUNT(DISTINCT(maps.id)) AS total_maps,
COUNT(layers.id) AS total_layers")
.joins(maps: :layers)
.group("clients.id")
end
In order for this to work, you need the associations declared between your models (Client has_many :maps, Map has_many :layers)
You can go depper in the ActiveRecord's query interface here

Speed Performance In Recursive SQL Requests

I have so category and this categories have unlimited sub category.
In Database Table, Fields are ID, UpperID and Title.
If I call a category and its subcategory in DataTable with recursive method in program(ASP.NET project)
performance is very bad.
And many user will use this application so everything goes bad.
Maybe All categories Fill to A Cache object and then we musnt go to Database.
But category count is 15000 or 20000.
So I think isn't a good method.
What can I do for fast performance?
Are you give me any suggestion?
caching or other in-memory-persistance is by far better than doing this on a relational system :) ... hey... it's oop!
just my 2 cents!
eg.
var categories = /* method for domain-objects*/.ToDictionary(category => category.ID);
foreach (var category in categories.Values)
{
if (!category.ParentCategoryID.HasValue)
{
continue;
}
Category parentCategory;
if (categories.TryGetValue(category.ParentCategoryID.Value, out parentCategory))
{
parentCategory.AddSubCategory(category);
}
}
et voila ... your tree is ready to go!
edit:
do you exactly know where your performance bottle-neck is?...
to give you some ideas, eg:
loading from database
building up the structure
querying the structure
loading from database:
then you should load it once and be sure to have some changetracking/notifying to get changes (if made) or optimize your query!
building up the structure:
the way i create the tree (traversal part) is the wastest you can do with a Dictionary<TKey, TValue>
querying the structure:
the structure i've used in my example is faster than List<T>. Dictionary<TKey, TValue> uses an index over the keys - so you may use int for the keys (IDs)
edit:
So you use DataTable to fix the
problem. Now you've got 2 problems: me
and DataTable
what do you have right now? where are you starting from? can you determine where your mudhole is? give us code!
Thanks All,
I find my solution with Common Table Expressions(CTE) fifty- fifty.
Its allow fast recursive queries.
WITH CatCTE(OID, Name, ParentID)
AS
(
SELECT OID, Name, ParentID FROM Work.dbo.eaCategory
WHERE OID = 0
UNION ALL
SELECT C.OID, C.Name, C.ParentID FROM Work.dbo.eaCategory C JOIN CatCTE as CTE ON C.ParentID= CTE.OID
)
SELECT * FROM CatCTE