Insert data from to a table - sql

I have a table that lists number of comments from a particular site like the following:
Date Site Comments Total
---------------------------------------------------------------
2010-04-01 00:00:00.000 1 5 5
2010-04-01 00:00:00.000 2 8 13
2010-04-01 00:00:00.000 4 2 7
2010-04-01 00:00:00.000 7 13 13
2010-04-01 00:00:00.000 9 1 2
I have another table that lists ALL sites for example from 1 to 10
Site
-----
1
2
...
9
10
Using the following code i can find out which sites are missing entries for the previous month:
SELECT s.site
from tbl_Sites s
EXCEPT
SELECT c.site
from tbl_Comments c
WHERE c.[Date] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)
Producing:
site
-----
3
5
6
8
10
I would like to be able to insert the missing sites that is listed from my query into the comments table with some default values, i.e '0's
Date Site Comments Total
---------------------------------------------------------------
2010-04-01 00:00:00.000 3 0 0
2010-04-01 00:00:00.000 5 0 0
2010-04-01 00:00:00.000 6 0 0
2010-04-01 00:00:00.000 8 0 0
2010-04-01 00:00:00.000 10 0 0
the question is, how did i update/insert the table/values?
cheers,
Lee

INSERT INTO CommentTable (Date, Site, Comments, Total)
SELECT '2010-04-01 00:00:00.000', Site, 0, 0
FROM SiteTable
WHERE Site NOT IN
(SELECT DISTINCT Site FROM CommmentTable
WHERE [Date] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0))

A Left Join from Site to your commenttable should do the work i guess
At least if I did unterstand your intention
EDIT : Sry thought you wanna select all sites with those comments

Related

Creating a new calculated column in SQL

Is there a way to find the solution so that I need for 2 days, there are 2 UD's because there are June 24 2 times and for the rest there are single days.
I am showing the expected output here:
Primary key UD Date
-------------------------------------------
1 123 2015-06-24 00:00:00.000
6 456 2015-06-24 00:00:00.000
2 123 2015-06-25 00:00:00.000
3 658 2015-06-26 00:00:00.000
4 598 2015-06-27 00:00:00.000
5 156 2015-06-28 00:00:00.000
No of times Number of days
-----------------------------
4 1
2 2
The logic is 4 users are there who used the application on 1 day and there are 2 userd who used the application on 2 days
You can use two levels of aggregation:
select cnt, count(*)
from (select date, count(*) as cnt
from t
group by date
) d
group by cnt
order by cnt desc;

Writing SQL INSERT which retrieves its data from two separate related rows

I am writing a SQL script that is to insert a new record using data from two rows that are under the same AccountID.
My table looks like the following:
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
My fix is to find find each 7,8 combination and insert a new row with ActivityId 78 that gets the DisplayDetails from ActivityId 7 and TransactionDate from ActivityId 8.
My queries looks like the following:
SELECT *
INTO #ActivityEight
FROM Account A
WHERE A.ActivityId = 8
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM #temp2 VL WITH(NOLOCK)
JOIN #ActivityEight S
ON VL.AccountId = S.AccountId
WHERE VL.ActivityId = 7
However when I run SELECT * FROM Account I get a 78 row for each 7 and 8 row, when I should only get 1 78 row per 7 and 8 combination.
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
=============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
1 78 DisplayThis1 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis2 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis1 1999-02-02 00:00:00.000 NULL
1 78 DisplayThis2 1999-02-02 00:00:00.000 NULL
I believe I can utilize the EnvironmentId to achieve the desired functionality, but I'm not sure how.
Any help would be appreciated.
Thanks!
I think this will help you
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM Account VL WITH(NOLOCK)
JOIN Account S ON VL.AccountId = S.AccountId and VL.EnvironmentId = S.EnvironmentId
WHERE VL.ActivityId = 7 and S.ActivityId = 8

SQL code to get count over each day of a range

I have a data.frame like below.
toolid startdate enddate stage
abc 1-Jan-13 5-Jan-13 production
abc 6-Jan-13 10-Jan-13 down
xyz 3-Jan-13 8-Jan-13 production
xyz 9-Jan-13 15-Jan-13 down
I want to get final output which will be like below. The output needs to return - count of each stage (there could be more than 2 stages) over each day between 1jan13 to 15jan13 (or any date range that an user wants). I was able to create the required result in R. I also wrote a cursor in SQL and it achieves the purpose. But is there a way to do the same without using cursors? I am looking for logic and direction.
date down production
1 2013-01-01 0 1
2 2013-01-02 0 1
3 2013-01-03 0 2
4 2013-01-04 0 2
5 2013-01-05 0 2
6 2013-01-06 1 1
7 2013-01-07 1 1
8 2013-01-08 1 1
9 2013-01-09 2 0
10 2013-01-10 2 0
11 2013-01-11 1 0
12 2013-01-12 1 0
13 2013-01-13 1 0
14 2013-01-14 1 0
15 2013-01-15 1 0
I think this may be what you want. It requires a recursive CTE to get a row for each day in the range.
with daterange as (
select startdate=min(startdate),enddate=max(enddate) from #source
), dates as (
select d=(select startdate from daterange) union all
select dateadd(day,1,d) from dates where d<(select enddate from daterange)
)
select
d,
down=(select count(*) from #source where d between startdate and enddate and stage='down'),
production=(select count(*) from #source where d between startdate and enddate and stage='production')
from dates
order by d;

MDX to sum over months with non-empty measure value for the month

This has been stumping me and I'm not sure why it is so difficult.
I have a measure that has empty values up until a certain point in time, and then starts having values. I want to get a monthly average, but only on those months that actually have a non-empty value. I also want my time range to be fixed for the query regardless of which months have values (for example, across the whole year)
Here is one variation of MDX that I tried:
WITH
MEMBER Measures.MonthsWithSales AS
(IIF( IsEmpty(([Time].[Month].CurrentMember,[Measures].[ProductsSold])), 0, [Measures].[MonthCount]))
MEMBER Measures.AvgProductsSold AS
[Measures].[ProductsSold] /Measures.MonthsWithSales
SELECT
{
[Measures].[ProductsSold], [Measures].[MonthCount],
[Measures].[MonthsWithSales], [Measures].[AvgProductsSold]
} ON 0,
[Time].[Month].Members ON 1
FROM MyCube
WHERE [Time].[Year].&[2010-01-01T00:00:00]
which returns something like this:
ProductsSold MonthCount MonthsWithSales AvgProductsSold
All 1644 12 **12** **137**
2010-01-01 00:00:00.000 (null) 1 0 (null)
2010-02-01 00:00:00.000 (null) 1 0 (null)
2010-03-01 00:00:00.000 (null) 1 0 (null)
2010-04-01 00:00:00.000 (null) 1 0 (null)
2010-05-01 00:00:00.000 (null) 1 0 (null)
2010-06-01 00:00:00.000 234 1 1 234
2010-07-01 00:00:00.000 237 1 1 237
2010-08-01 00:00:00.000 236 1 1 236
2010-09-01 00:00:00.000 232 1 1 232
2010-10-01 00:00:00.000 232 1 1 232
2010-11-01 00:00:00.000 233 1 1 233
2010-12-01 00:00:00.000 240 1 1 240
The problem is on the ALL row.
I expect that the MonthsWithSales across the whole year returns 7 not 12
and that AvgProductsSold (per month with sales) is 234.86 not 137.
I realize that it's not doing what I want because it's using the MonthCount at the ALL level. But I do not know how to "sink into" the "per month dimension" to sum up the MonthCount only on the relevant months when it is calculating the "ALL".
I assumed you have 2 levels on the month hierarchy: one with the All member and one for the months.
MEMBER Measures.AvgProductsSold AS
IIf([Time].[Month].CurrentMember.Level.Ordinal = 0
, Avg([Time].[Month].CurrentMember.Children, [Measures].[ProductsSold])
, [Measures].[ProductsSold])
(You may have to replace [Time].[Month].CurrentMember.Children with [Time].[Month].Members)
The Avg function computes the average on the non empty values.
Here is the query I am likely to end up using, properly using my time hierarchy:
WITH
MEMBER [Measures].[MonthsWithSales]
AS
COUNT
(
FILTER
(
DESCENDANTS([Time].[YQMD].CurrentMember,[Time].[YQMD].[Month]),
NOT ISEMPTY([Measures].[ProductsSold])
)
)
MEMBER
[Measures].[AvgProductsSold]
AS
[Measures].[ProductsSold]/[Measures].[MonthsWithSales]
SELECT
{
[Measures].[ProductsSold],
[Measures].[MonthsWithSales],
[Measures].[AvgProductsSold]
} ON 0,
[Time].[Month].Members ON 1
FROM MyCube
The [YQMD] is a time hierarchy with Levels: 1 Year, 2 Quarter, 3 Month, 4 Date

How to query to get totals for last seven days?

I am using SQL Server 2008.
I want to write a query that gives me total activity for a number of given days. Specifically, I want to count total votes per day for the last seven days.
My table looks like this:
VoteID --- VoteDate -------------- Vote --- BikeID
1 2012-01-01 08:24:25 1 1234
2 2012-01-01 08:24:25 0 5678
3 2012-01-02 08:24:25 1 1289
4 2012-01-03 08:24:25 0 1234
5 2012-01-04 08:24:25 1 5645
6 2012-01-05 08:24:25 0 1213
7 2012-01-06 08:24:25 1 1234
8 2012-01-07 08:24:25 0 1125
I need my results to look like this
VoteDate ---- Total
2012-01-01 5
2012-01-02 6
2012-01-03 7
2012-01-04 1
2012-01-05 3
My thought is that I have to do something like this:
SELECT SUM(CASE WHEN Vote = 1 THEN 1 ELSE 0 END) AS Total
FROM Votes
GROUP BY VoteDate
This query doesn't work because it counts only votes that occurred (almost exactly) at the same time. Of course, I want to look only at a specific day. How do I make this happen?
Cast it as a date:
SELECT
cast(VoteDate as date) as VoteDate,
SUM(CASE WHEN Vote = 1 THEN 1 ELSE 0 END) AS Total
FROM Votes
WHERE VoteDate between dateadd(day, -7, GETDATE()) and GETDATE()
GROUP BY cast(VoteDate as date)
Your VoteDate column is a datetime, but you just want the date part of it. The easiest way to do that is to cast it as a date type. You can read more about SQL Server date types here.
And if your Vote column is either 1 or 0, you can just do sum(vote) as Total instead of doing the case statement.
SELECT SUM(Vote) As Total, YEAR(VoteDate),Month(VoteDate),Day(VoteDate)
FROM Votes
Group By YEAR(VoteDate),Month(VoteDate),Day(VoteDate)
Some SQL Server functions that may be of interest
Some MySQL functions that may be of interest