Forming SQL Query and Passing The Result To The View - sql

I have this view method -
public ActionResult Index()
{
var db = new ApplicationDbContext();
var auctions = db.Auctions.ToArray();
return View(auctions);
}
which correctly returns an array of all auctions in my database. But I want to return just the most popular ones. I want to do something like this:
public ActionResult Index()
{
var db = new ApplicationDbContext();
var auctions = db.Auctions.getMostPopular.ToArray();
return View(auctions);
}
Where getMostPopular() is a method in my model containing all my auctions and looks like so at the moment:
public static List<Auction> getMostPopular()
{
var query = "SELECT* FROM AUCTIONS WHERE EndTime > CONVERT(date, GETDATE()) ORDER BY viewCount DESC;" }
}
So how do I correctly write this getMostPopular() method?
And is this the correct path to go writing it in the model? Or should I write the query in the controller Index action, and if so what would that look like?

Correct is relative. Your proposed SQL statement would seem to do the trick. Ordering the results by the ViewCount desc would appear to be the main part of implementing your method get most popular. If you're already considering a date filter, you might also consider the top clause such as select top 10 * from Table order by ViewCount desc, to only consider a fixed number of most popular items.

Related

Transforming Raw Sql to Laravel equolent

I have written this SQL code
SELECT drugs.*, COUNT(*) as 'views' from drugs INNER JOIN drug_seen on drugs.id = drug_seen.drug_id GROUP BY drugs.id order by views ASC
And now I am trying to write in in the Laravel equolent but I am facing some troubles.
This is what I have tried
$drugs = Drug::select(DB::raw('drugs.*,count(*) as views'))
->join('drug_seen', 'drugs.id', 'drug_seen.drug.id')
->groupBy('drug.id')->orderByRaw('views');
I am having errors like column not found i think the code is not written properly
Drug class
class Drug extends Model
{
use HasFactory;
use SoftDeletes;
...
...
...
public function drugVisits()
{
return $this->hasMany(DrugSeen::class);
}
Hop this will solve your problem.
$drugs = Drug::with('drugVisits')->get();
$drugs->count(); //for total records in drugs table.
You have typo error in join instead on drug_id you use drug.id
Try this:
$drugs = Drug::select(DB::raw('drugs.*,count(*) as views'))
->join('drug_seen', 'drugs.id', 'drug_seen.drug_id')
->groupBy('drugs.id')->orderByRaw('views');
}
As soon as you use join() you're leaving Eloquent and entering Query\Builder, losing the benefits of Model configurations in the process. And with() eager-loads aren't the answer, if you're looking to filter the results by both tables. What you want is whereHas().
Also, as far as your grouping and count manipulation there, I think you're looking more for Collection handling than SQL groups.
$drugModel = app(Drugs::class);
$results = $drugModel->whereHas('drugVisits')->with('drugVisits')->get();
$organizedResults = $results
->groupBy($drugModel->getKey())
->sortyBy(function (Drugs $drugRecord) {
return $drugRecord->drugVisits->count();
});
If you want to have a 'views' property that carries the count in the root-level element, it would look like this:
$drugModel = app(Drugs::class);
$results = $drugModel->whereHas('drugVisits')->with('drugVisits')->get();
$organizedResults = $results
->groupBy($drugModel->getKey())
->map(function (Drugs $drugRecord) {
$drugRecord->views = $drugRecord->drugVisits->count();
return $drugRecord;
});
->sortyBy('views');

how to make a subquery using the query builder of laravel

I want to do the following mysql query with the query builder of Laravel 7:
SELECT r.id, (SELECT date FROM posts as pp where r.id = pp.request_id
ORDER BY STR_TO_DATE(SUBSTRING(pp.date, 1, 19),'%Y-%m-%dT%H:%i:%s') DESC limit 1), r.delivery_mode FROM requests AS r
LEFT JOIN posts AS p ON r.id = p.request_id
group by r.id;
However unfortunately I don't understand how to obtain the latests post date for every request using the query builder of Laravel. I suppose I should do a subquery as in the query above. This is my code:
$query = DB::table('requests');
$query->select(DB::raw('DISTINCT(requests.id)'),'requests.delivery_mode',DB::raw('posts.date'));
$query->leftJoin('posts', 'requests.id', '=', 'posts.request_id');
$requests_list = $query->get();
In the table posts, the date is a string in this format: 2020-04-16T12:46:33+02:00. So I used that complicated functions because I want to see only the latest date post grouped by id_request, that is the foreign key of the table posts connected with the primary key id of the table requests. A request can have many posts.
Can help?
PS:
I found the solution:
$query = DB::table('requests');
$query->select(DB::raw('DISTINCT(requests.id)'),'requests.delivery_mode',DB::raw("(SELECT date FROM posts as pp where requests.id = pp.request_id ORDER BY STR_TO_DATE(SUBSTRING(pp.date, 1, 19),'%Y-%m-%dT%H:%i:%s') DESC limit 1) as lastPostDate"));
$query->leftJoin('posts', 'requests.id', '=', 'posts.request_id');
$requests_list = $query->get();
Probably it isn't a pretty solution but it works!.
Request Model
public function posts()
{
return $this->hasMany(Post::class);
}
Post Model
public function request()
{
return $this->belongsTo(Request::class);
}
Controller
public function index()
{
$date = Post::has("request")
->orderBy(...) // add your order by condition here
->limit(1)
->pluck("date");
$requests = Request::with("posts")
->where("date", $date)
->get();
return $requests;
}

Typo3 9.5 - Custom flexform ordering, wrong backquotes in sql

i have an custom extension, where you can select the different entries at the backend, to show them at the list view. I have a custom sorting at my backend, but the system always sort them Descending.
I implemented an "orderBy" function, which doesnt work, because the system uses wrong backspaces.
My code looks like this:
I call the sort function in my "findByUid($uid)" function like this:
$query->setOrderings($this->orderByKey('uid', $uidArray));
protected function orderByKey($key, $uidlist) {
$order = array();
foreach ($uidlist as $uid) {
//$order["$key=$uid"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
$order["$key=$uid"] = "ASC";
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($order);
}
return $order;
}
The result at the sql query is:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid=3` DESC
But it must be:
ORDER BY `tx_MYEXTENSION_domain_model_FIELD`.`uid` = 3 DESC
Is there a way to change this?
After a lot of search, I found this solution on an stackoverflow entry:
$ids = explode(',',$this->settings['entries'])
foreach($ids as $key => $id){
$entries[$id] = $this->entriesRepository->findByUid($id);
}
This code snippet has to be intergrated at the controller.
For me its working.

Group By Sum Linq to SQL in C#

Really stuck with Linq to SQL grouping and summing, have searched everywhere but I don't understand enough to apply other solutions to my own.
I have a view in my database called view_ProjectTimeSummary, this has the following fields:
string_UserDescription
string_ProjectDescription
datetime_Date
double_Hours
I have a method which accepts a to and from date parameter and first creates this List<>:
List<view_UserTimeSummary> view_UserTimeSummaryToReturn =
(from linqtable_UserTimeSummaryView
in datacontext_UserTimeSummary.GetTable<view_UserTimeSummary>()
where linqtable_UserTimeSummaryView.datetime_Week <= datetime_To
&& linqtable_UserTimeSummaryView.datetime_Week >= datetime_From
select linqtable_UserTimeSummaryView).ToList<view_UserTimeSummary>();
Before returning the List (to be used as a datasource for a datagridview) I filter the string_UserDescription field using a parameter of the same name:
if (string_UserDescription != "")
{
view_UserTimeSummaryToReturn =
(from c in view_UserTimeSummaryToReturn
where c.string_UserDescription == string_UserDescription
select c).ToList<view_UserTimeSummary>();
}
return view_UserTimeSummaryToReturn;
How do I manipulate the resulting List<> to show the sum of the field double_Hours for that user and project between the to and from date parameters (and not separate entries for each date)?
e.g. a List<> with the following fields:
string_UserDescription
string_ProjectDescription
double_SumOfHoursBetweenToAndFromDate
Am I right that this would mean I would have to return a different type of List<> (since it has less fields than the view_UserTimeSummary)?
I have read that to get the sum it's something like 'group / by / into b' but don't understand how this syntax works from looking at other solutions... Can someone please help me?
Thanks
Steve
Start out by defining a class to hold the result:
public class GroupedRow
{
public string UserDescription {get;set;}
public string ProjectDescription {get;set;}
public double SumOfHoursBetweenToAndFromDate {get;set;}
}
Since you've already applied filtering, the only thing left to do is group.
List<GroupedRow> result =
(
from row in source
group row by new { row.UserDescription, row.ProjectDescription } into g
select new GroupedRow()
{
UserDescription = g.Key.UserDescription,
ProjectDescription = g.Key.ProjectDescription,
SumOfHoursBetweenToAndFromDate = g.Sum(x => x.Hours)
}
).ToList();
(or the other syntax)
List<GroupedRow> result = source
.GroupBy(row => new {row.UserDescription, row.ProjectDescription })
.Select(g => new GroupedRow()
{
UserDescription = g.Key.UserDescription,
ProjectDescription = g.Key.ProjectDescription,
SumOfHoursBetweenToAndFromDate = g.Sum(x => x.Hours)
})
.ToList();

Retrieving Data in Webmatrix without 'foreach'

I want to retrieve a single item of data from my database to then use as a value for an input element.
Using the below will retrieve each instance of SubmittedBy in the DB so results in multiple results.
var UserId = WebSecurity.CurrentUserId;
var db = Database.Open("testDB");
var selectQueryString = "Select SubmittedBy FROM Posts WHERE UserId=#0";
var data = db.Query(selectQueryString, UserId);
#foreach(var row in data)
{
<input type="email" name="emailfrom" id="emailfrom" value="#SubmittedBy"/>
}
How do I retrieve SubmittedBy so it only gives the one result i.e. without the foreach loop?
Thanks in advance!!!
If by your data restriccions are you going to obtain 1 and only 1 value for an specific UserId, you could use
var SubmyttedValue = db.QueryValue(selectQueryString, UserId);
There is a method created specifically for this purpose called QuerySingle - just change your query like this:
var data = db.QuerySingle(selectQueryString, UserId);
I hope this helps!
Change your query like this:
Select SubmittedBy FROM Posts WHERE UserId=#0 LIMIT 1