Get click statistics count grouped by month - sql-server

Been trying to find a proper solution, but have so far been unable to understand or find one properly.
Have the following DB:
I am trying to get the number of clicks in each month.
So i would get something like:
--------------
January - 10
February - 7
March - 22
etc.
This is my code so far:
var MonthlyCount = from c in ClickStatistics
group c.LogDate by new { date = c.LogDate, Id = c.ID }into grp
select new{
Month = grp.Key.date.Month,
Clicks = grp.Key.Id
};
But right now i am just getting this:

Groups items together that have the same c.LogDate.Month. Selects the first item of the group to extract the month as text value (we grouped by month so they should all be equal in that regard) and counts the number of entries in the group.
var ClickStatistics = new List<Clicks>()
{
new Clicks() { ID = 1, LogDate = DateTime.Now.AddMonths(-1)},
new Clicks() { ID = 2, LogDate = DateTime.Now.AddMonths(-1)},
new Clicks() { ID = 3, LogDate = DateTime.Now.AddMonths(0)},
new Clicks() { ID = 4, LogDate = DateTime.Now.AddMonths(0)},
new Clicks() { ID = 5, LogDate = DateTime.Now.AddMonths(1)},
};
var MonthlyCount = from c in ClickStatistics
group c by new { date = c.LogDate.Month } into grp
select new
{
Month = grp.First().LogDate.ToString("MMMM"),
Clicks = grp.Count(),
};

Related

I need to create a new expense card

I need to create a new expense card, the input parameters are Amount, Date and Description.
Fields that must be filled in the expense card to create it:
Card keeper is contact
Months Expenses Applications is a custom object
When creating an expense card, if Months Expenses Applications exists by the date entered in the "Date" field, then a new expense card is created from which Months Expenses Applications is taken from the existing one
if, by the date entered in the "date" field, there is no Months Expenses Applications, you need to create Months Expenses Applications and then create an expense map in which Months Expenses Applications will have a new Months Expenses Applications created
I tried to create an expense map with "Amount" "Date" "Description" equal to the input parameters, but I don't know how to specify MonthExpenseApplication__c
public static void createNewExpenseCard(Integer amount, Date createdDate, String description) {
Month_Expense_Application__c MonthApplication = [
SELECT Name, MonthDate__c
FROM Month_Expense_Application__c
WHERE MonthDate__c =: createdDate
];
if (MonthApplication != null) {
ExpenseCard__c exp = new ExpenseCard__c(
Amount__c = amount,
CardDate__c = createdDate,
Description__c = description,
CardKeeper__c = '0034x00001K7kGCAAZ'
);
exp.MonthExpenseApplication__c = [
SELECT MonthExpenseApplication__c
FROM ExpenseCard__c
WHERE MonthExpenseApplication__c =: MonthApplication.Id
].Id;
insert exp;
} else {
Month_Expense_Application__c monthApp = new Month_Expense_Application__c(
Balance__c = 1000,
MonthDate__c = createdDate,
Keeper__c = '0034x00001K7kGCAAZ'
);
ExpenseCard__c exp2 = new ExpenseCard__c(
Amount__c = amount,
CardDate__c = createdDate,
Description__c = description,
CardKeeper__c = '0034x00001K7kGCAAZ'
);
insert exp2;
}
}
This is dangerous:
Month_Expense_Application__c MonthApplication = [
SELECT Name, MonthDate__c
FROM Month_Expense_Application__c
WHERE MonthDate__c =: createdDate
];
If there are zero results it will throw "list has no rows for assignment". Similar if there's more than 1.
Something like this?
Integer amount = 50;
Date createdDate = System.today();
String description = 'Lorem ipsum...';
Month_Expense_Application__c app;
List<Month_Expense_Application__c> applications = [SELECT Id
FROM Month_Expense_Application__c
WHERE MonthDate__c =: createdDate
LIMIT 1];
if(applications.isEmpty()){
app = new Month_Expense_Application__c(
Balance__c = 1000,
MonthDate__c = createdDate,
Keeper__c = '0034x00001K7kGCAAZ'
);
insert app;
} else {
app = applications[0];
}
// one way or another - the monthly allowance exists now. So just use its id in the lookup
ExpenseCard__c exp = new ExpenseCard__c(
Amount__c = amount,
CardDate__c = createdDate,
Description__c = description,
CardKeeper__c = '0034x00001K7kGCAAZ',
Month_Expense_Application__c = app.Id
);
There are more elegant ways to do it, you'd need to read up about upsert and external ids - but it should be good enough.

Power BI-Customer purchase count

I need to detect the number of customers who make purchases in the 2 stores with a single formula
data:
Result:
1 Person
Create this below measure-
person_count =
var total_shop_count = DISTINCTCOUNT(your_table_name[Shop])
var tab =
SUMMARIZE(
your_table_name,
your_table_name[Name],
"shop_count",DISTINCTCOUNT(your_table_name[Shop])
)
return
COUNTROWS(
FILTER(
tab,
[shop_count] = total_shop_count
)
)
Here is the output-

Days count across the months with given start date and end date

I have a snippet of a table as below :
Can somebody help me with the query that gives me report as below:
If you don't want to use a calendar dimension as Mike suggested (which is a good idea) the best option may be a user defined table function (UDTF). This UDTF does not depend on the DAYS_COUNT column. It calculates the days in each month and only requires a start and end date. It will generate as many rows as are required to fill the months in between.
select * from a, table(DAYS_IN_MONTHS(START_DATE, END_DATE));
create or replace function DAYS_IN_MONTHS(START_DATE date, END_DATE date)
returns table(MONTHS string, DAYS float)
language javascript
strict immutable
as
$$
{
initialize: function (argumentInfo, context) {},
processRow: function (row, rowWriter, context) {
let year = row.START_DATE.getFullYear();
let month = row.START_DATE.getMonth();
let endYear = row.END_DATE.getFullYear();
let endMonth = row.END_DATE.getMonth();
let isDone = year > endYear || (year == endYear && month > endMonth);
if (year == endYear && month == endMonth) {
rowWriter.writeRow({MONTHS: `${year}-${(""+(month+1)).padStart(2, '0')}`,DAYS: row.END_DATE.getDate() - row.START_DATE.getDate()});
isDone = true;
}
d = row.START_DATE
while (!isDone) {
if (year == endYear && month == endMonth) {
rowWriter.writeRow({MONTHS: `${year}-${(""+(month+1)).padStart(2, '0')}`,DAYS: row.END_DATE.getDate() - (d.getDate() - 1) });
isDone = true;
} else {
rowWriter.writeRow({MONTHS: `${year}-${(""+(month+1)).padStart(2, '0')}`,DAYS: new Date(year, month + 1, 0).getDate() - (d.getDate() - 1) });
month++;
if (month == 12) {
month = 0;
year++;
}
}
d = new Date(year, month, 1);
}
},
finalize: function (rowWriter, context) {},
}
$$;
It would be very helpful if you'd have a calendar dimension for something like this. As an example, you can create one with something like this:
CREATE TEMP TABLE calendar AS
SELECT dateadd(day,seq4(),'2017-01-01'::date) as cal_date,
date_trunc(month,cal_date) as cal_month_start,
dateadd(day,-1,(dateadd(month,1, cal_month_start))) as cal_month_end
FROM table(generator(rowcount => 10000));
With this calendar table, you can then join to it using the start and end dates and aggregate on that date to get the results. Using a CTE to replicate your data:
WITH x AS (
SELECT member_id, start_date, end_date
FROM (VALUES ('461043068_02','2018-08-07'::date,'2018-08-17'::date),
('461043068_01','2019-05-28'::date,'2019-06-28'::date)
) y (member_id, start_date, end_date)
)
Now, you can query x and join to calendar as such:
SELECT member_id, cal_month_start, count(*)
FROM x
JOIN calendar c
ON c.cal_date between dateadd(day,1,x.start_date) and x.end_date
GROUP BY 1,2;
This gives you the results you are looking for. Please note the need to add 1 to the start_date, so that you don't count the "edges" of your date ranges twice.
Also, I didn't format the cal_month_start in my query, but you can do that using a TO_VARCHAR() function, if needed.

Select specific columns with repository in Entity Framework Core

I have a big table with a binary column for picture. I need to show contents of this table in a view and make it searchable. I have tried only selecting a subset of columns that are needed in this. However, the generated SQL always has all the columns of the table in the generated query.
public IQueryable<ApplicantDTO> GetApplicantQueryable()
{
return DataContext.Applicants
.Include(a => a.Nationality)
.Select(x => new ApplicantDTO
{
Id = x.Id,
BirthDate = x.BirthDate,
Gender = x.Gender,
FirstName = x.FirstName,
LastName = x.LastName,
OtherName = x.OtherName,
MobileNo = x.MobileNo,
Age = x.Age,
Nationality = x.Nationality.National,
Admitted = x.admitted,
Completed = x.Completed
})
.Where(a => a.Admitted == false && a.Completed == true)
.OrderBy(a => a.LastName)
.AsNoTracking();
}
But instead of just specifying the above rows, the generated SQL from profiler is
SELECT
[a].[Id], [a].[BirthDate], [a].[BirthPlace], [a].[CompleteDate],
[a].[Completed], [a].[ContentType], [a].[CreateDate],
[a].[Denomination], [a].[Disability], [a].[Email],
[a].[FirstName], [a].[Gender], [a].[HomeTown], [a].[LastName],
[a].[MarryStatus], [a].[MatureApp], [a].[MobileNo], [a].[NationalityID],
[a].[OtherName], [a].[Passport], [a].[Pin], [a].[PostalAddress],
[a].[Region], [a].[Religion], [a].[ResAddress], [a].[SerialNo],
[a].[Title], [a].[VoucherID], [a].[admitted], [a.Nationality].[National]
FROM
[Applicants] AS [a]
INNER JOIN
[Nationality] AS [a.Nationality] ON [a].[NationalityID] = [a.Nationality].[Id]
WHERE
([a].[admitted] = 0)
AND ([a].[Completed] = 1)
ORDER BY
[a].[LastName]
With all the underlying columns all included in the query.
I tried putting it in an anonymous type before casting it to the ApplicantDTO but still the same effect.
What's wrong?

How to use IN Clause for list of strings or GUID's in Dapper

I am trying to write a dapper query for IN clause, but it's not working throwing casting error saying "Conversion failed when converting the nvarchar value 'A8B08B50-2930-42DC-9DAA-776AC7810A0A' to data type int." . In below query fleetAsset is Guid converted into string.
public IQueryable<MarketTransaction> GetMarketTransactions(int fleetId, int userId, int rowCount)
{
//Original EF queries which I am trying to convert to Dapper
//var fleetAsset = (from logicalFleetNode in _context.LogicalFleetNodes
// where logicalFleetNode.LogicalFleetId == fleetId
// select logicalFleetNode.AssetID).ToList();
////This query fetches guid of assetprofiles for which user having permissions based on the assets user looking onto fleet
//var assetProfileIds = (from ap in _context.AssetProfileJoinAccounts
// where fleetAsset.Contains(ap.AssetProfile.AssetID) && ap.AccountId == userId
// select ap.AssetProfileId).ToList();
var fleetAsset = _context.Database.Connection.Query<string>("SELECT CONVERT(varchar(36),AssetID) from LogicalFleetNodes Where LogicalFleetId=#Fleetid",
new { fleetId }).AsEnumerable();
//This query fetches guid of assetprofiles for which user having permissions based on the assets user looking onto fleet
var sql = String.Format("SELECT TOP(#RowCount) AssetProfileId FROM [AssetProfileJoinAccounts] AS APJA WHERE ( EXISTS (SELECT " +
"1 AS [C1] FROM [dbo].[LogicalFleetNodes] AS LFN " +
"INNER JOIN [dbo].[AssetProfile] AS AP ON [LFN].[AssetID] = [AP].[AssetID]" +
" WHERE ([APJA].[AssetProfileId] = [AP].[ID]) " +
" AND ([APJA].[AccountId] = #AccountId AND LogicalFleetId IN #FleetId)))");
var assetProfileIds = _context.Database.Connection.Query<Guid>(sql, new { AccountId = userId, FleetId = fleetAsset, RowCount=rowCount });
Dapper performs expansion, so if the data types match, you should just need to do:
LogicalFleetId IN #FleetId
(note no parentheses)
Passing in a FleetId (typically via an anonymous type like in the question) that is an obvious array or list or similar.
If it isn't working when you remove the parentheses, then there are two questions to ask:
what is the column type of LocalFleetId?
what is the declared type of the local variable fleetAsset (that you are passing in as FleetId)?
Update: test case showing it working fine:
public void GuidIn_SO_24177902()
{
// invent and populate
Guid a = Guid.NewGuid(), b = Guid.NewGuid(),
c = Guid.NewGuid(), d = Guid.NewGuid();
connection.Execute("create table #foo (i int, g uniqueidentifier)");
connection.Execute("insert #foo(i,g) values(#i,#g)",
new[] { new { i = 1, g = a }, new { i = 2, g = b },
new { i = 3, g = c },new { i = 4, g = d }});
// check that rows 2&3 yield guids b&c
var guids = connection.Query<Guid>("select g from #foo where i in (2,3)")
.ToArray();
guids.Length.Equals(2);
guids.Contains(a).Equals(false);
guids.Contains(b).Equals(true);
guids.Contains(c).Equals(true);
guids.Contains(d).Equals(false);
// in query on the guids
var rows = connection.Query(
"select * from #foo where g in #guids order by i", new { guids })
.Select(row => new { i = (int)row.i, g = (Guid)row.g }).ToArray();
rows.Length.Equals(2);
rows[0].i.Equals(2);
rows[0].g.Equals(b);
rows[1].i.Equals(3);
rows[1].g.Equals(c);
}

Resources