DAX - Inactive customers - ssas

I have a measure like below which returns me all active customers who in the last 90 days bought product category = 'A'
CustomersActive last 90 days:=
VAR Last90Days=
MAX (DimDate[Date) - 90
RETURN
CALCULATE (
DISTINCTCOUNT ( FactSales[CustomerKey]);
DimProduct[Category] = "A";
FILTER (
ALL (DimDate[Date);
DimDate[Date] >= Last90Day
&& DimDate[Date] <= MAX (DimDate[Date])
)
)
Now I need to create a measure INACTIVE CUSTOMERS:
Rule:
Make a list of all distinct customers whose someday bought product = "B" and the date of this was less than my actual filter date
Create a measure using also a distinct count of the last 90 days, but comparing the first list to my actual
If customer was in the first list (product B) and in my last 90 days (product A) is not appearing, then 1, else 0

Related

I need to get items sold to customers that didn't buy it in 2 years or never at all

I'm triyng to get a list of items that have been sold to customers that didn't for 2 years o never...
BUt I need to validate all customers and items. something like
Customer 1 item 1 bought now after 2 years ago should appear
Customer 1 item 2 bought 1 year ago shouldn't appear
Customer 1 item 3 bought today never bought before should appear
And so on with all customers and Items...
So far Ive tried creating a view with items not sold in 24 month
SELECT dbo.qry_ItemsTangoSoloHabilitadosConLista.COD_ARTICU, dbo.qry_Facturacion.COD_CLIENT, dbo.qry_Facturacion.RAZONSO, dbo.qry_Facturacion.DESCRIPCION, MAX(dbo.qry_Facturacion.FECHA_MOV) AS Expr1,
dbo.qry_ItemsTangoSoloHabilitadosConLista.DESCRIP
FROM dbo.qry_Facturacion INNER JOIN
dbo.qry_ItemsTangoSoloHabilitadosConLista ON dbo.qry_Facturacion.COD_ARTICU = dbo.qry_ItemsTangoSoloHabilitadosConLista.COD_ARTICU
WHERE (DATEDIFF(month, dbo.qry_Facturacion.FECHA_MOV, GETDATE()) > 24)
GROUP BY dbo.qry_Facturacion.COD_CLIENT, dbo.qry_Facturacion.RAZONSO, dbo.qry_Facturacion.DESCRIPCION, dbo.qry_Facturacion.T_COMP, dbo.qry_ItemsTangoSoloHabilitadosConLista.COD_ARTICU,
dbo.qry_ItemsTangoSoloHabilitadosConLista.DESCRIP
HAVING (LEN(dbo.qry_ItemsTangoSoloHabilitadosConLista.COD_ARTICU) > 5) AND (dbo.qry_Facturacion.T_COMP = 'FAC')
And then used it on another view along the orders table joining items and Customers showing last month, but results are at least waaay wrong, or strange....
SELECT dbo.qry_NoVendidos24meses.RAZON_SOCI, dbo.qry_NoVendidos24meses.COD_ARTICU, dbo.qry_NoVendidos24meses.DESCRIPCIO, dbo.qry_Facturacion.FECHA_MOV, dbo.qry_Facturacion.CANTIDAD,
dbo.qry_Facturacion.COD_CLIENT, dbo.qry_NoVendidos24meses.DESCRIP
FROM dbo.qry_NoVendidos24meses LEFT OUTER JOIN
dbo.qry_Facturacion ON dbo.qry_NoVendidos24meses.RAZON_SOCI = dbo.qry_Facturacion.RAZONSO AND dbo.qry_NoVendidos24meses.COD_ARTICU = dbo.qry_Facturacion.COD_ARTICU
WHERE (dbo.qry_Facturacion.FECHA_MOV IS NULL) OR
(dbo.qry_Facturacion.FECHA_MOV >= DATEADD(mm, - 1, GETDATE()))
What am I doing wrong... ?
I Have a table with ITEMS ( qry_ItemsTangoSoloHabilitadosConLista) An invoiced items (who- what -when named qry_facturacion) and a customers table (qry_CLientes)

Dax Measure - Value table compare value

I have a table FactSales
And tried but didn’t get ant satisfactory result.
Id like to calculate old results and compare to my actual one and see how many customers whose bought product B before (before 90 days) didn’t buy the same product in last 3 months according to the date filter
I tried this:
Customers inactive =
VAR Daysbefore90: Max(DimDate[date]) -90
> RETURN CALCULATE( DISTINCTCOUNT(FSales[CustomerKey]); DimProduct[Product] = “A”; FILTER( ALL ( DimDate[Date] );
DimDate[Date] < DaysBefore90 ); NOT(CONTAINS( FILTER(FSales;
RELATED(DimDate[Date]) >= Daysbefore90 && DimDate[Date]) <=
MAX(Daysbefore90): RELATED(DimProduct[Product]) = “A”) ;
FSales[CustomerKey]; FSales[CustomerKey] ) ) )
This will get you all customer who purchased item 'B' in the last 90 Days:
Customers Who Bought Product B 90 Days Ago :=
CALCULATE (
DISTINCTCOUNT ( 'FSale'[CustomerKey] ),
ALL ( 'DimDate'[Date] ),
KEEPFILTERS (
DATESINPERIOD ( 'DimDate'[Date], MAX ( 'DimDate'[Date] ), -90, DAY )
),
KEEPFILTERS ( DimProduct[Product] = "B" )
)
Your question is a little hard to read, so maybe update it and we can go from there.

Join two Queries so that the second query becomes a row in the results of query 1

I have two queries that I would like to combine so i can make a chart out of the results.
The results have to be very specific or the chart will not display the information properly
I am using MS SQL in Crystal Reports 11
Below is the results I am looking for.
Date Invoice Type Amount
2012/08 Customer Payment 500
2012/08 Customer Invoice 1000
2012/08 Moving Balance 1500
2012/09 Customer Invoice 400
2012/09 Moving Balance 1900
2012/10 Interest 50
2012/10 Moving Balance 1950
So the First query returns the following results
Date Invoice Type Amount
2012/08 Customer Payment 500
2012/08 Customer Invoice 1000
2012/09 Customer Invoice 400
2012/10 Interest 50
and the second query returns
Date Invoice Type Amount
2012/08 Moving Balance 1500
2012/09 Moving Balance 1900
2012/10 Moving Balance 1950
The second query is very long and complicated with a join .
What is the best way of joining these two queries
so that I have one column called invoice Type ( as the chart is based on this field)
that covers all the invoice types plus the moving balance
I assume that the place of the Moving Balance rows inside the result set is important.
You can do something like this:
select date, invoice_type, amount
from
(
select date, invoice_type, amount from query1
union all
select date, invoice_type, amount from query2
)
order by date, case invoice_type when 'Moving Balance' then 1 else 0 end
This first appends the results of the second query to the results of the first query and then reorders the resulting list first by date and then by the invoice type in such a way that the row with Moving balance will come last.
With the actual queries you have given, it should look something like this:
select date, invoice_type, amount
from
(
SELECT
CONVERT(VARCHAR(7),case_createddate, 111) AS Date,
case_invoicetype as invoice_type,
Sum(case_totalexvat) as amount
FROM cases AS ca
WHERE case_primaryCompanyid = 2174 and
datediff(m,case_createddate,getDate())
union all
select
CONVERT(VARCHAR(7),ca.case_createddate, 111) AS Date,
'Moving Balance' as Invoice_Type,
sum(mb.Amount) as Amount
from
cases as ca
left join (
select
case_primaryCompanyId as ID,
case_createdDate,
case_TotalExVat as Amount
from
cases
) mb
on ca. case_primaryCompanyId = mb.ID
and ca.case_createdDate >= mb.case_CreatedDate
where
ca.case_primaryCompanyId = 2174 and
ca.case_createdDate > DATEADD(m, -12, current_timestamp)
group by
case_primaryCompanyId,
CONVERT(VARCHAR(7),ca.case_createddate, 111)
order by ca.case_primaryCompanyid, CONVERT(VARCHAR(7),ca.case_createddate, 111)
)
order by date, case invoice_type when 'Moving Balance' then 1 else 0 end
You can use Union and can use Order by clause
Select * from (Query 1
Union
Query 2
) as a Order by a.Date Asc

SQL query to identify seasonal sales items

I need a SQL query that will identify seasonal sales items.
My table has the following structure -
ProdId WeekEnd Sales
234 23/04/09 543.23
234 30/04/09 12.43
432 23/04/09 0.00
etc
I need a SQL query that will return all ProdId's that have 26 weeks consecutive 0 sales. I am running SQL server 2005. Many thanks!
Update: A colleague has suggested a solution using rank() - I'm looking at it now...
Here's my version:
DECLARE #NumWeeks int
SET #NumWeeks = 26
SELECT s1.ProdID, s1.WeekEnd, COUNT(*) AS ZeroCount
FROM Sales s1
INNER JOIN Sales s2
ON s2.ProdID = s1.ProdID
AND s2.WeekEnd >= s1.WeekEnd
AND s2.WeekEnd <= DATEADD(WEEK, #NumWeeks + 1, s1.WeekEnd)
WHERE s1.Sales > 0
GROUP BY s1.ProdID, s1.WeekEnd
HAVING COUNT(*) >= #NumWeeks
Now, this is making a critical assumption, namely that there are no duplicate entries (only 1 per product per week) and that new data is actually entered every week. With these assumptions taken into account, if we look at the 27 weeks after a non-zero sales week and find that there were 26 total weeks with zero sales, then we can deduce logically that they had to be 26 consecutive weeks.
Note that this will ignore products that had zero sales from the start; there has to be a non-zero week to anchor it. If you want to include products that had no sales since the beginning, then add the following line after `WHERE s1.Sales > 0':
OR s1.WeekEnd = (SELECT MIN(WeekEnd) FROM Sales WHERE ProdID = s1.ProdID)
This will slow the query down a lot but guarantees that the first week of "recorded" sales will always be taken into account.
SELECT DISTINCT
s1.ProdId
FROM (
SELECT
ProdId,
ROW_NUMBER() OVER (PARTITION BY ProdId ORDER BY WeekEnd) AS rownum,
WeekEnd
FROM Sales
WHERE Sales <> 0
) s1
INNER JOIN (
SELECT
ProdId,
ROW_NUMBER() OVER (PARTITION BY ProdId ORDER BY WeekEnd) AS rownum,
WeekEnd
FROM Sales
WHERE Sales <> 0
) s2
ON s1.ProdId = s2.ProdId
AND s1.rownum + 1 = s2.rownum
AND DateAdd(WEEK, 26, s1.WeekEnd) = s2.WeekEnd;

sql query to find customers who order too frequently?

My database isn't actually customers and orders, it's customers and prescriptions for their eye tests (just in case anyone was wondering why I'd want my customers to make orders less frequently!)
I have a database for a chain of opticians, the prescriptions table has the branch ID number, the patient ID number, and the date they had their eyes tested. Over time, patients will have more than one eye test listed in the database. How can I get a list of patients who have had a prescription entered on the system more than once in six months. In other words, where the date of one prescription is, for example, within three months of the date of the previous prescription for the same patient.
Sample data:
Branch Patient DateOfTest
1 1 2007-08-12
1 1 2008-08-30
1 1 2008-08-31
1 2 2006-04-15
1 2 2007-04-12
I don't need to know the actual dates in the result set, and it doesn't have to be exactly three months, just a list of patients who have a prescription too close to the previous prescription. In the sample data given, I want the query to return:
Branch Patient
1 1
This sort of query isn't going to be run very regularly, so I'm not overly bothered about efficiency. On our live database I have a quarter of a million records in the prescriptions table.
Something like this
select p1.branch, p1.patient
from prescription p1, prescription p2
where p1.patient=p2.patient
and p1.dateoftest > p2.dateoftest
and datediff('day', p2.dateoftest, p1.dateoftest) < 90;
should do... you might want to add
and p1.dateoftest > getdate()
to limit to future test prescriptions.
This one will efficiently use an index on (Branch, Patient, DateOfTest) which you of course should have:
SELECT Patient, DateOfTest, pDate
FROM (
SELECT (
SELECT TOP 1 DateOfTest AS last
FROM Patients pp
WHERE pp.Branch = p.Branch
AND pp.Patient = p.Patient
AND pp.DateOfTest BETWEEN DATEADD(month, -3, p.DateOfTest) AND p.DateOfTest
ORDER BY
DateOfTest DESC
) pDate
FROM Patients p
) po
WHERE pDate IS NOT NULL
On way:
select d.branch, d.patient
from data d
where exists
( select null from data d1
where d1.branch = d.branch
and d1.patient = d.patient
and "difference (d1.dateoftest ,d.dateoftest) < 6 months"
);
This part needs changing - I'm not familiar with SQL Server's date operations:
"difference (d1.dateoftest ,d.dateoftest) < 6 months"
Self-join:
select a.branch, a.patient
from prescriptions a
join prescriptions b
on a.branch = b.branch
and a.patient = b.patient
and a.dateoftest > b.dateoftest
and a.dateoftest - b.dateoftest < 180
group by a.branch, a.patient
This assumes you want patients who visit the same branch twice. If you don't, take out the branch part.
SELECT Branch
,Patient
FROM (SELECT Branch
,Patient
,DateOfTest
,DateOfOtherTest
FROM Prescriptions P1
JOIN Prescriptions P2
ON P2.Branch = P1.Branch
AND P2.Patient = P2.Patient
AND P2.DateOfTest <> P1.DateOfTest
) AS SubQuery
WHERE DATEDIFF(day, SubQuery.DateOfTest, SubQuery.DateOfOtherTest) < 90