Group by Date bigger than SQL Server - sql-server

I'm working with Micrososft SqlServer 2012 and I have this table:
Table
+-----------+--------+------------+
| Id_Client | Amount | Date |
+-----------+--------+------------+
| 1 | 100 | 24/08/2015 |
| 2 | 100 | 24/07/2015 |
| 3 | 100 | 24/06/2015 |
| 3 | 100 | 24/05/2015 |
+-----------+--------+------------+
And I need to make a query like this:
Query
SELECT ID_CLIENT,
CASE WHEN DATE <= '01/07/2015' THEN 'OLD' ELSE 'NEW' END,
SUM(AMOUNT) FROM TABLE
GROUP BY ID_CLIENT
How do I Group by Date with the condition, instead of each Date?
I expect something like:
Expected result
+---+-----+-----+
| 1 | NEW | 100 |
| 2 | NEW | 100 |
| 3 | OLD | 200 |
+---+-----+-----+

Related

Create materialized view from multiple tables with identical schemas

I am trying create a materialized view in Redshift.
I have 100 tables of the form
user_1
user_2
...
user_100
Each table has the same schema. For example:
user_1
| id | user_id | date | expense |
|----|---------|----------|---------|
| 1 | 1 | 20200521 | 200 |
| 2 | 2 | 20200601 | 100 |
| 3 | 1 | 20200603 | 90 |
user_2
| id | user_id | date | expense |
|----|---------|----------|---------|
| 1 | 1 | 20200521 | 250 |
| 2 | 3 | 20200204 | 10 |
| 3 | 2 | 20200403 | 50 |
What I want to do is to create a materialized view which has all the rows from all 100 tables.
The objective is to run a queries to calculate the sum(expense) for given user_id between certain dates.
So my materialized view will be something like this:
user_1
| id | user_id | date | expense |
|----|---------|----------|---------|
| 1 | 1 | 20200521 | 200 |
| 2 | 2 | 20200601 | 100 |
| 3 | 1 | 20200603 | 90 |
| 4 | 1 | 20200521 | 250 |
| 5 | 3 | 20200204 | 10 |
| 6 | 2 | 20200403 | 50 |
I am having trouble with the CREATE query for this view.
Any guidance on the query to create this view is appreciated.
Thank you.
How about UNIONing the tables?
Keep in mind the difference between UNION (does implicit distinct) and UNION ALL which just combines rows from two tables as they come.
CREATE MATERIALIZED VIEW users
AS
SELECT * FROM user_1 UNION ALL
SELECT * FROM user_2 UNION ALL
SELECT * FROM user_3 UNION ALL
...
SELECT * FROM user_100

Find the newest entry of a crosstable per record?

I have three tables:
My products with their IDs and their features.
is a table with treatments of my products with a treatment-ID, a method, and a date. The treatments are done in batches of many products so there is a crosstable
with the products IDs and the treatment IDs and a bool value for the success of the treatment.
Each product can undergo many different treatments so there is a many-to-many relation. I now want to add to the product table (1.) for every product a value that shows the method of its most recent successful treatment if there is any.
I made a query that groups the crosstable's entries by product-ID but I don't know how to show the method and date of it's last treatment.
table 1:
| productID | size | weight | height | ... |
|-----------|:----:|-------:|--------|-----|
| 1 | 13 | 16 | 9 | ... |
| 2 | 12 | 17 | 12 | ... |
| 3 | 11 | 15 | 15 | ... |
| ... | ... | ... | ... | ... |
table 2:
| treatmentID | method | date |
|-------------|:--------:|-----------:|
| 1 | dye blue | 01.02.2016 |
| 2 | dye red | 01.02.2017 |
| 3 | dye blue | 01.02.2018 |
| ... | ... | ... |
table 3:
| productID | treatmentID | success |
|-----------|:-----------:|--------:|
| 1 | 1 | yes |
| 1 | 2 | yes |
| 1 | 3 | no |
| ... | ... | ... |
I need table 1 to be like:
table 1:
| productID | size | weight | height | latest succesful method |
|-----------|:----:|-------:|--------|-------------------------|
| 1 | 13 | 16 | 9 | dye red |
| 2 | 12 | 17 | 12 | ... |
| 3 | 11 | 15 | 15 | ... |
| ... | ... | ... | ... | ... |
My query:
SELECT table3.productID, table2.method
FROM table2 INNER JOIN table3 ON table2.treatmentID = table3.treatmentID
GROUP BY table3.productID, table2.method
HAVING (((table3.productID)=Max([table2].[date])))
ORDER BY table3.productID DESC;
but this does NOT show only one (the most recent) entry but all of them.
Simplest solution here would be to write either a subquery within your sql, or create a new query to act as a subquery(it will look like a table) to help indicate(or elminate) the records you want to see.
Using similar but potentially slightly different source data as you only gave one example.
Table1
| ProductID | Size | Weight | Height |
|-----------|------|--------|--------|
| 1 | 13 | 16 | 9 |
| 2 | 12 | 17 | 12 |
| 3 | 11 | 15 | 15 |
Table2
| TreatmentID | Method | Date |
|-------------|------------|----------|
| 1 | dye blue | 1/2/2016 |
| 2 | dye red | 1/2/2017 |
| 3 | dye blue | 1/2/2018 |
| 4 | dye yellow | 1/4/2017 |
| 5 | dye brown | 1/5/2018 |
Table3
| ProductID | TreatmentID | Success |
|-----------|-------------|---------|
| 1 | 1 | yes |
| 1 | 2 | yes |
| 1 | 3 | no |
| 2 | 4 | no |
| 2 | 5 | yes |
First order of business is to get the max(dates) and productIds of successful treatments.
We'll do this by aggregating the date along with the productIDs and "success".
SELECT Table3.productid, Max(Table2.Date) AS MaxOfdate, Table3.success
FROM Table2 INNER JOIN Table3 ON Table2.treatmentid = Table3.treatmentid
GROUP BY Table3.productid, Table3.success;
This should give us something along the lines of:
| ProductID | MaxofDate | Success |
|-----------|-----------|---------|
| 1 | 1/2/2018 | No |
| 1 | 1/2/2017 | Yes |
| 2 | 1/4/2017 | No |
| 2 | 1/8/2017 | Yes |
We'll save this query as a "regular" query. I named mine "max", you should probably use something more descriptive. You'll see "max" in this next query.
Next we'll join tables1-3 together but in addition we will also use this "max" subquery to link tables 1 and 2 by the productID and MaxOfDate to TreatmentDate where success = "yes" to find the details of the most recent SUCCESSFUL treatment.
SELECT table1.productid, table1.size, table1.weight, table1.height, Table2.method
FROM ((table1 INNER JOIN [max] ON table1.productid = max.productid)
INNER JOIN Table2 ON max.MaxOfdate = Table2.date) INNER JOIN Table3 ON
(Table2.treatmentid = Table3.treatmentid) AND (table1.productid = Table3.productid)
WHERE (((max.success)="yes"));
The design will look something like this:
Design
(ps. you can add queries to your design query editor by clicking on the "Queries" tab when you are adding tables to your query design. They act just like tables, just be careful as very detailed queries tend to bog down Access)
Running this query should give us our final results.
| ProductID | Size | Weight | Height | Method |
|-----------|------|--------|--------|-----------|
| 1 | 13 | 16 | 9 | dye red |
| 2 | 12 | 17 | 12 | dye brown |

Count rows which has the same ID and display on the table

This is the original table:
| ID | Card_No |
|----+---------|
| 1 | 6453671 |
| 1 | 8795732 |
| 1 | 9948495 |
| 2 | 7483009 |
| 2 | 1029001 |
| 3 | 7463094 |
Is it possible to make it like this? Which will be adding a calculated column the the original table?
| ID | Card_No | Total |
|----+---------|-------|
| 1 | 6453671 | 3 |
| 1 | 8795732 | 3 |
| 1 | 9948495 | 3 |
| 2 | 7483009 | 2 |
| 2 | 1029001 | 2 |
| 3 | 7463094 | 3 |
I'm using Microsoft Access, and I've tried code like this:
SELECT ID, COUNT (*) AS Total FROM Table GROUP BY ID
But I did not get the result I want.
First of all, saving the calculated value back into table is not only unnecessary but bad design.
Options:
build a report that counts records with an expression in textbox
build aggregate query then another query joining aggregate query to the table
DCount() domain aggregate function in query

how to check date records with in fdate and tdate range in sql server

Hi friends i have small doubt in sql server
here i want data based on condition
same id and status is equal to s then that date value be
how to write query in sql server
Table :emp
id |status |date(mm-dd-yy) |fdate(mm-dd-yy) |tdate(mm-dd-yy)
1 | S |03-16-11 | |
1 | b | | 03-15-11 |03-18-11
1 | s |03-17-11 | |
1 | b | | 04-20-12 |04-30-12
1 | S |04-20-12 | |
1 | s |04-10-12 | |
1 | s |10-01-14 | |
1 | b | |10-02-14 |10-25-14
2 | s |01-18-12 | |
2 | b | |01-18-12 |01-28-12
2 | b | |03-10-13 |03-24-13
2 | s |03-16-13 | |
2 | s |03-10-13 | |
2 | s |03-23-13 | |
2 | b | |04-20-13 |04-27-13
2 | s |07-01-14 | |
the table (status = s, id, date) compare it with status = b, same id number and date ( Date value from status s) with the date range of fdate and tdate .
if that data with in range then Billing yes other wise billing no
output like
id |status |date(mm-dd-yy) |fdate(mm-dd-yy) |tdate(mm-dd-yy) |Billing
1 | S |03-16-11 | | |yes
1 | s |03-17-11 | | |yes
1 | S |04-20-12 | | |yes
1 | s |04-10-12 | | |no
1 | s |10-01-14 | | |no
2 | s |01-18-12 | | |yes
2 | s |03-16-13 | | |yes
2 | s |03-10-13 | | |yes
2 | s |03-23-13 | | |yes
2 | s |07-01-14 | | |no
i tried query like below
select *
from ( select * from emp a where status ='s') a
inner join (select * from emp b where status='b') b
on a.pn=b.pn
where a.date<=b.date1 and a.date>=b.date2
its not give exactely result.
please tell me how to write query in sql server .
Try
select a.Id,
a.status,
a.date,
a.fdate,
a.tdate,
max(IsNull(case when a.date between b.fDate and b.tDate
then 'yes'
else 'no'
end, 'no')) Billing
from emp a
left join emp b
on a.Id=b.Id
where a.status ='s'
and b.status = 'b'
group by a.Id,
a.status,
a.date,
a.fdate,
a.tdate
Some questions/comments:
What are the fields: pn, date1 and date2?
date1 in your query is, I guess, bigger than date2

Finding the max and min date values in SQL Server tables

I have two tables:
A lookup table (tabOne):
KEY | Group | Name | Desc | Val_Key
----------------------------------------
1 | a | NameA | DescA | 10
2 | b | NameB | DescB | 20
3 | c | NameC | DescC | 30
4 | d | NameD | DescD | 40
5 | e | NameE | DescE | 50
6 | f | NameF | DescF | 60
A second table containing readings (tabTwo):
KEY | Date | Reading | Val_Key
----------------------------------------
1 | Date | Read | 10
2 | Date | Read | 20
3 | Date | Read | 40
4 | Date | Read | 40
5 | Date | Read | 30
6 | Date | Read | 20
7 | Date | Read | 40
8 | Date | Read | 20
9 | Date | Read | 10
10 | Date | Read | 20
11 | Date | Read | 50
12 | Date | Read | 60
What I need to do is join tabTwo with TabOne and create a column with the newest Reading and a column with the oldest reading for each item in the group column of TabOne.
At the end of the day I want a table that look as follow:
KEY | Group | Name | Desc | Val_Key | LastReading | FirstReading |
-------------------------------------------------------------------------
1 | a | NameA | DescA | 10 | | |
2 | b | NameB | DescB | 20 | | |
3 | c | NameC | DescC | 30 | | |
4 | d | NameD | DescD | 40 | | |
5 | e | NameE | DescE | 50 | | |
6 | f | NameF | DescF | 60 | | |
Thanks!
Freddie
If this is Sql Server 2005 or newer, outer apply will help:
select TabOne.*,
last.Reading LastReading,
first.Reading FirstReading
from TabOne
outer apply
(
select top 1
Reading
from TabTwo
where TabTwo.Val_Key = TabOne.val_Key
order by TabTwo.Date desc
) last
outer apply
(
select top 1
Reading
from TabTwo
where TabTwo.Val_Key = TabOne.val_Key
order by TabTwo.Date asc
) first
Live test is # Sql Fiddle.
#Nikola Markovinović's solution can be made more universally applicable if the subqueries are moved directly to the main query's SELECT clause, which is possible each of them retrieves only one value and is, therefore, valid as a scalar expression:
SELECT
t1.[KEY],
t1.[Group],
t1.Name,
t1.[Desc],
t1.Val_Key,
(
SELECT TOP 1 Reading
FROM TabTwo
WHERE Val_Key = t1.Val_Key
ORDER BY Date DESC
) AS LastReading,
(
SELECT TOP 1 Reading
FROM TabTwo
WHERE Val_Key = t1.Val_Key
ORDER BY Date ASC
) AS FirstReading
FROM TabOne t1
If you needed e.g. dates along the way, you would probably have to stick to Nikola's solution. There is an alternative to it, but it's more cumbersome (albeit more standard too): it would involve grouping TabTwo's data by Val_Key to get earliest/latest dates per Val_Key, then joining back to TabTwo to access entire rows corresponding to the found dates to finally pull the necessary columns, and ultimately joining both result sets to TabOne to get the final column set.

Resources