How to get aggregate count with date attribute via linq - sql

I have a table of data where I'm recording hits on a website. The table tracks the timestamp of the hit as well as the source. I want to pull hits per day, with the counts categorized by the source. So the result would be something like
{
google: {
{ 01/01/2000, 123 }, // date, count of hits for that date
{ 01/02/2000, 134 },
{ 01/03/2000, 223 },
{ 01/04/2000, 145 },
},
yahoo: {
{ 01/01/2000, 223 },
{ 01/02/2000, 434 },
{ 01/03/2000, 123 },
{ 01/04/2000, 135 },
}
}
Is there a way to get this data aggregated in this format using linq? At the moment I can get the aggregate totals of the source / count using
var counts = tableName.GroupBy(x => x.ColumnId)
.Select(g => new { g.Key, Count = g.Count() });
but adding the additional date attribute is eluding me.

You need to perform grouping again by date:
var counts = tableName
.GroupBy(x => x.ColumnId)
.Select(g => new
{
Category = g.Key,
Items = g.GroupBy(x => x.Date.Date)
.Select(x => new
{
Date = x.Key,
Count = x.Count()
})
.ToList()
});

Related

Strapi GROUP BY and COUNT fields with the same value

Is there any way in strapi to group by entries with the same fields and count its total?
Trying to create a Poll App which has "Response" Collection containing an "Answer" Field (enum: a, b, c, d). Would like to group responses with the same answers. Something like this:
{
"answer": "a",
"total": 3
}, {
"answer": "b",
"total": 1
}
Is it possible out of the box?
To give more context, here's its sql counterpart:
select *, count(answers) from responses group by answers
there is no known default way for groupby with entity service, however there is count query:
/src/answer/controllers/answer.js
const { createCoreController } = require("#strapi/strapi").factories;
module.exports = createCoreController("api::answer.answer", ({ strapi }) => ({
async find(ctx) {
let { query } = ctx;
let answers = await strapi.db.query("api::answer.answer").findMany({
...query,
});
answers = await Promise.all(answers.map(async (answer) => ({
...answer,
total: await strapi.db.query("api::answer.answer").count({where: '...'})
})))
return answers
},
}));
or you can use raw query like this:
let { rows } = await strapi.db.connection.raw(
`select id from posts where published_at IS NOT null order by random() limit ${count};
`);
or
let { rows } = await strapi.db.connection.raw(
`select *, count(answers) from responses group by answers;`);

Vue.js filter values from two store

I need help with getters in Vue.js, I'm trying to get list of data that is connected with id in two different stores.
Here is structure:
pageUser {
pageId,
userId,
type,
weight
}
user {
id,
name,
age,
city
}
This is code I have for now:
state: () => {
return {
images: [
{id: '1', name:'John', age: 23, city: 'Boston'},
{id: '2', name:'Jack', age: 34, city: 'Miami'}
]
}
},
getters: {
list: (state, pageId) => (key) => {
return map(state[key], function (s) {
return {
id: s.id,
name: s.name,
age: s.age,
city: s.city
}
})
}
This return me list of all users, but I need to make some filtering, when I go to page for example with id '2586' I need to get list of user that belong that page and they should be sorted by weight.
I'm pretty new in Vue.js and I really don't know how to make this.
getters: {
getUser: state => id => {
return user
// Create a new array of objects merging both the states
.map(u => {
return {
...pageUser.find(pu => pu.userId === u.id),
u
}
})
// Filter by id provided to the getter
.filter(u => u.id === id)
// Sort on basis of weight
.sort((a,b) => {
if (a.weight < b.weight) {
return -1
}
else if (a.weight > b.weight)) {
return 1
}
return 0
})
}
}
Call the getter in your component:
this.$store.getters.getUser('2586')

Duplicate items in list after an API update

I'm learning vuejs and I'm doing a weather app, the goal is to rank cities with an index (humidex). I fetch weather information by API (axios) in order to collect data from several cities. I want to auto update data every x minutes, problem : some of my results are duplicated (the new data don't replace the old one).
I tried to set an unique key (based on latitude and longitude) for each item, it works for several results but not for all.
data () {
return {
items:[],
show: false,
cities: cities,
newCity:''
}
},
components: {
Item
},
computed: {
sortHumidex() {
return this.items.slice().sort((a,b) => {
return this.getHumidex(b) - this.getHumidex(a) || b.current.temp_c - a.current.temp_c
})
}
},
methods: {
addCity() {
if (this.newCity.trim().length == 0) {
return
}
this.cities.push(this.newCity)
this.newCity = ''
},
getHumidex: (el) => {
const e = 6.112 * Math.pow(10,(7.5*el.current.temp_c/(237.7+el.current.temp_c)))
*(el.current.humidity/100)
return Math.round(el.current.temp_c + 5/9 * (e-10))
},
indexGeo: (e) => {
const lat = Math.round(Math.abs(e.location.lat))
const lon = Math.round(Math.abs(e.location.lon))
return lat.toString() + lon.toString()
},
getApi: function () {
const promises = [];
this.cities.forEach(function(element){
const myUrl = apiUrl+element;
promises.push(axios.get(myUrl))
});
let self = this;
axios
.all(promises)
.then(axios.spread((...responses) => {
responses.forEach(res => self.items.push(res.data))
}))
.catch(error => console.log(error));
}
},
created() {
this.getApi()
this.show = true
}
}
The render when I update API :
By pushing to the existing array of items, you have to deal with the possibility of duplicates. This can be eliminated simply by replacing items every time the API call is made.
Replace:
responses.forEach(res => self.items.push(res.data))
with:
self.items = responses.map(res => res.data)

I Can't GroupBy arrays using computed in Vue.js

i want help on this. Thank you.
I have an object :
Funding : [
{person_id:'1';
Amount : '100'},
{person_id:'1';
Amount : '200'},
{person_id:'2';
Amount : '150'},
I would like to groupBy Funding by person_id and get the sum of Amount in each group.
I use this code but nt working ..
Groupe(array,key) {
const result = {}
array.forEach(funding => {
if (!result[funding[person_id]]){
result[funding[person_id]] = []
}
result[funding[person_id]].push(item)
})
return result
}
I created two different examples, one a function will return the summed amount of just one of the keys. In the second, it will return the summed amount of all the keys.
Here is a codepen for that https://codepen.io/aquilesb/pen/BvbqMd
const data = [
{
person_id:'1',
amount : '100'},
{
person_id:'2',
amount : '150'
},
{
person_id:'1',
amount : '150'
},
{
person_id:'2',
amount : '70'
}
];
const personID = '1';
// return by a key
const groupByKey = (list, key) => list.reduce((acc, item) => {
if (item.person_id === key) {
return parseInt(item.amount, 10) + acc;
}
return acc;
}, 0);
//return the sum of all keys
const groupAll = list => list.reduce((acc, item) => {
const accAmout = acc[item.person_id] || 0;
return Object.assign({}, acc, {[item.person_id]: accAmout + parseInt(item.amount, 10)});
}, {});
console.log("groupByKey", groupByKey(data, personID));
console.log("groupAll", groupAll(data));
You can use lodash's .groupBy function and .reduce functions to group by Person ID first, and then add the amounts together. Using a computed property in Vue makes this very easy, and you can access the object in your template like its a regular property.
Vue/HTML Template
<div id="app">
<ul v-for="(total,personId) in fundingByPerson">
<li>Persond ID: {{personId}}, Amount : ${{total.toFixed(2)}}</li>
</ul>
</div>
Javascript
// Include lodash via `npm install lodash`
import _ from 'lodash';
new Vue({
el: "#app",
data() {
return {
Funding: [
{person_id:'1', Amount : '130'},
{person_id:'1', Amount : '200'},
{person_id:'2', Amount : '350'},
{person_id:'45', Amount : '150'}
]
}
},
computed: {
// Group by Person, then add amounts together
fundingByPerson: function(){
let byPerson = _.groupBy(this.Funding, 'person_id');
let totals = {};
// Loop over each Group of Amounts, indexed by personId
_.forEach(byPerson, function(amounts, personId){
totals[personId] = _.reduce( byPerson[personId], function(sum, entry){
return sum + parseFloat( entry.Amount );
}, 0);
})
return totals;
} // fundingByPerson
})
Here's a working fiddle: http://jsfiddle.net/mdy59c7e/6/

Ravedb Index that aggregates over list using filters

{
"Id": "products/214429",
"Title": "RADIO SYMPHONY ORCHESTR - VERDI: OPERA CHORUSES",
"CategoryId": 91166,
"CategoryName": "Classical",
"Prices": [
{
"UserGroupId": 2129,
"PriceAmount": 24.91
},
{
"UserGroupId": 934,
"PriceAmount": 34.91
},
{
"UserGroupId": 30,
"PriceAmount": 14.28
}
]
}
I am trying to create index for minimal/maximal value for attributes that are stored as list in model above. List contains list of usergroups for product and price value for that group. I want to be able to query that index by filtering with list of provided Usergroups and to get MIN or MAX only for those usergroups that are provided in query.
For instance if User is in groups 934 and 2129 I do not want to calculate value from group 30 in query aggregation so min price should be 24.91, not 14.28 (from group 30).
Calculating the MIN and MAX values in the index will not perform because you would have to calculate for each possible combination of usergroups. But what you can do is map the usergroup price like this and then do a sort on the amountprice either asc or desc depending if you want to have MIN or MAX.
public class ProductUserGroupPrices : AbstractIndexCreationTask<Product, Product>
{
public ProductUserGroupPrices()
{
Map = products => from product in products
from price in product.Prices
select new
{
UserGroupId = price.UserGroupId
PriceAmount = price.PriceAmount,
ProductId = product.Id
};
Sort(x => x.PriceAmount, SortOptions.Double);
Stores.Add(x => x.PriceAmount, FieldStorage.Yes);
}
}
The query to get the MIN price for a product for a list of usergroupids would look something like this. (note that I haven't tested this code)
public class ProductUserGroupPrice
{
public double PriceAmount { get; set; }
}
This query will not get the documents as results, but the values from the index. In this case the priceAmount because we have said in the index definition it should be stored.
var results = session.Advanced.LuceneQuery<Product>("ProductUserGroupPrices")
.SelectFields<ProductUserGroupPrice>()
.WhereEquals(x => x.ProductId, productId)
.AndAlso()
.WhereIn(x => x.UserGroupId, userGroupIds)
.OrderBy(x => x.PriceAmount)
.FirstOrDefault();