SQL - Change row/column structure of existing query - sql

I'm a die hard Excel VBA fan and having to make the transition to a very basic SQL based piece of software. I have managed to adapt an existing query to my needs (still not sure how !) but I could do with some help to further tweek it :)
The query is:
PARAMETERS [Date From] DateTime, [Date To] DateTime, [Site Group] Text;
SELECT Contacts.Name, DataProfile.Date, DataProfile.TotalUnits
FROM (Lookup INNER JOIN Groups ON Lookup.Lookup_Id = Groups.Lookup_Id) INNER JOIN (Contacts INNER JOIN (Points INNER JOIN DataProfile ON Points.Id = DataProfile.Point_Id) ON Contacts.Id = Points.Contacts_Id) ON Groups.Link_Id = Contacts.Id
WHERE (((Lookup.Lookup_Name)=[Site Group]) AND ((DataProfile.Date) Between [Date From] And [Date To]) AND ((Points.Type)='Electricity') AND ((DataProfile.Type)=0))
AND Contacts.Group_1=[Client Group]
ORDER BY Contacts.Name, DataProfile.Date;
This produces a list of daily totals by site by day and looks like :
Site.......Date.........Value
Site 1....01/01/13...444.7
Site 1....02/01/13...861.5
Site 1....03/01/13...850.0
etc...
Is it possible to write the query to output as :
Site.....01/01/13....02/01/13....03/01/13
Site1....444.7.......861.5.........850.0
Site2....111.1.......222.2.........333.3
etc...
It would make my life so much easier to have one row per site rather than so many. At the moment I am coding excel to adapt the data - but it's long and not efficient. If I could get SQL to output in this format I would be like some kind of office god !!!
Any help/advise/guidence is welcome :)

What version of SQL are you running?
Can you use PIVOT?
http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

Related

How to make a sub-query based on query results in SQL

I'm currently trying to query a list of our assembly items, along with their corresponding components.
I've been trying this query a few different ways, here is where I'm currently at (closest I've gotten)
SELECT inv_mast.item_id AS [Item ID]
,inv_mast.item_desc AS [Item Description]
,IMC.item_id AS [Component Item ID]
FROM inv_mast
INNER JOIN assembly_line ON inv_mast.inv_mast_uid = assembly_line.inv_mast_uid
LEFT JOIN inv_mast IMC ON assembly_line.component_inv_mast_uid = inv_mast.inv_mast_uid
WHERE inv_mast.item_id = 'LFV-SV59Z-2ZGD-LOGO-L'
In the "Assembly_line" table there is a Component_inv_mast_uid which I need to use to query our Item ID's for the components (inv_mast joins to assembly_line on the inv_mast_uid)
It should export something like this:
LFV-SV59Z-2ZGD-LOGO-L (LFV-SV59Z-2ZGD-L)
LFV-SV59Z-2ZGD-LOGO-L (Print Fee)
I forgot to mention what is currently exporting.
When I run this query, it provides most information correct, however the "Component Item ID" column is returning Null, and I'm not sure why.
I've only had experience so far with joining basic tables, so subqueries are very new to me.
try to use
WHERE inv_mast.item_id like 'LFV-SV59Z-2ZGD-LOGO-L%'
instead of = 'LFV-SV59Z-2ZGD-LOGO-L'

COUNT Clicks/Opens for Engagement Scoring

I am a bit rusty on SQL so any assistance is appreciated. I am also referencing my SQL textbook but I thought I would try this out.
I am developing a lead scoring model starting with engagement scoring. I created a data extension to house the results and used the following query to populate:
SELECT a.[opportunityid],
a.[first name],
a.[last name],
a.[anticipatedentryterm],
a.[funnelstage],
a.[programofinterest],
a.[opportunitystage],
a.[opportunitystatus],
a.[createdon],
a.[ownerfirstname],
a.[ownerlastname],
a.[f or j visa student],
a.[donotbulkemail],
a.[statecode],
Count(DISTINCT c.[subscriberkey]) AS 'Clicks',
Count(DISTINCT b.[subscriberkey]) AS 'Opens',
Count(DISTINCT b.[subscriberkey]) * 1.5 +
Count(DISTINCT c.[subscriberkey]) * 3 AS 'Probability'
FROM [ug_all_time_joined] a
INNER JOIN [open] b
ON a.[opportunityid] = b.[subscriberkey]
INNER JOIN [click] c
ON a.[opportunityid] = c.[subscriberkey]
GROUP BY a.[opportunityid],
a.[first name],
a.[last name],
a.[anticipatedentryterm],
a.[funnelstage],
a.[programofinterest],
a.[opportunitystage],
a.[opportunitystatus],
a.[createdon],
a.[ownerfirstname],
a.[ownerlastname],
a.[f or j visa student],
a.[donotbulkemail],
a.[statecode]
Something is wrong with my COUNT functions, the query populates the same value in both Clicks and Opens and I don't think it's accurate. The result I am aiming for is how many times a subscriber id appears (which would correspond with the individual clicks/opens, each row is a 1 action).
Thank you!
Why is that surprising?
You have two joins that if you take to their logical conclusion imply that
b.[SubscriberKey] = c.[SubscriberKey]
Hence, counting distinct values will be the same.
You have not provide sample data or desired results. I can speculate, though, that you intend LEFT JOINs so you get some values in one table that are not matched in the other.
When you do an inner join, between a and b, your data is filtered when you join a and c, which will give you incorrect results. having no view of your data and no background of your tables, this is the best guess i have

Need MS Access Form Field to automatically Calculate and Allocate Costs based on given Parameters

Below is my mock database that I am using. I have four different tables: Tbl_MainDatabase, Tbl_InsuranceCoverage, Tbl_MatterDetail, and Tbl_PaymentProcessing.
What I want -
I want my form to determine the remaining Retention Limit (i.e., Retention Limit for the applicable policy - sum of invoices for the same Claim Number )
According to the mock database, the required answer should be [ $2500 - (300+700+355)] as highlighted for your convenience
What I tried
I used the help of Graphical representation through the following query:
SELECT [Claim Number], Sum([Net Invoice Amount])
FROM [PaymentProcessing]
GROUP BY [Claim Number]
This method works to show me how much I spent per claim number so far in the form of a graph. However I want to display the remaining amount.
Any Help is appreciated :)
I am one month old at using Access. But I am trying my best to learn
Thank you in advance!
SELECT
IC.[Retention Limit]-SUM([Net Invoice Amt]) AS Remaining, MD.[Claim Number], IC.[Retention Limit], IC.InsuranceID
FROM tbl_InsuranceCoverage IC
INNER JOIN tbl_MatterDetail MD ON ic.InsuranceID = MD.Policy
INNER JOIN tbl_PaymentProcessing PP ON MD.MatterDetailID=pp.MatterDetailID AND MD.[Claim Number]=pp.[Claim Number]
GROUP BY MD.[Claim Number], IC.[Retention Limit], IC.InsuranceID
See if this works. Havent tested it but seems simple. You can remove the extra columns, but this will hlep you understand joins a bit
For All the New users The above code by #Doug Coats works perfectly.
Make Sure All the Foreign Key and Primary Keys is linked in the Relationship Property. ( One of the way To do this in the Query is - Right click on the Query and select Design View --> Right click again on the grey space and Select Show all Tables Now Drag your Primary Key of the table and drop at the foreign Key on the other table --> This will create a relationship between both for the Query Purpose.
This will also Prevent Data from Duplication in the query then use a similar code as described by Doug Coats in the above comment in the SQL View
SELECT [Insurance Coverage].[Retention Unit]-Sum([Net Invoice Amount]) AS Remaining, [Matter Detail].[Claim Number], [Insurance Coverage].[Retention Unit], [Matter Detail].Policy
FROM (([Main Database] INNER JOIN [Matter Detail] ON [Main Database].[Database ID] = [Matter Detail].[Short Name]) INNER JOIN [Payment Processing] ON ([Matter Detail].[Matter Detail ID] = [Payment Processing].[Matter Detail ID]) AND ([Main Database].[Database ID] = [Payment Processing].[Short Name])) INNER JOIN [Insurance Coverage] ON [Matter Detail].Policy = [Insurance Coverage].[Insurance ID]
GROUP BY [Matter Detail].[Claim Number], [Insurance Coverage].[Retention Unit], [Matter Detail].Policy;
You can then display this query in the form - I am still evaluating best way to display this query probably in a Combo Box (Not sure if any other controls has a row source)
Thank you

SQL Query extremely slow when including NOT LIKE or a current row reference in a subquery

I have the following query in SQL Server 2008 R2:
SELECT
DateName(month, DateAdd(month, [sfq].[fore_quart_month], -1)) AS [Month],
[sfq].[fore_quart_so_rev] AS [Sales Orders Revenue],
[sfq].[fore_quart_so_mar] AS [Sales Orders Margin],
[sfq].[fore_quart_mac_rev] AS [MAC Revenue],
[sfq].[fore_quart_mac_mar] AS [MAC Margin],
[sfq].[fore_quart_total_rev] AS [TOTAL Revenue],
[sfq].[fore_quart_total_mar] AS [TOTAL Margin],
(SELECT SUM([FORE].[Revenue])
FROM [SO_Opportunity][SO]
LEFT JOIN [SO_Type] ON [SO].[SO_Type_RecID] = [SO_Type].[SO_Type_RecID]
LEFT JOIN [SO_Opportunity_Audit][soa] ON [so].[Opportunity_RecID] = [soa].[Opportunity_RecId]
LEFT JOIN [SO_Opportunity_Audit_Value][soav] ON [soa].[SO_Opportunity_Audit_RecId] = [soav].[SO_Opportunity_audit_recid]
LEFT JOIN [SO_Forecast_dtl] [FORE] ON [SO].[Opportunity_RecID] = [FORE].[Opportunity_RecID]
WHERE ([SO_Type].[Description] NOT LIKE '%MAC%' AND [SO_Type].[Description] NOT LIKE '%Maint%')
AND YEAR([soa].[last_Updated_utc]) = #p_year AND MONTH([soa].[last_updated_utc]) = [sfq].[fore_quart_month]
AND [soav].[audit_value] LIKE '%Closed - Won%' AND [soav].[audit_token] = 'new_value'
AND [so].[SO_Opp_Status_RecID] = 7) AS [Rev]
FROM
[authmanager2].[dbo].[sales_forecast_quarterly][sfq]
WHERE
[sfq].[fore_quart_year] = #p_year AND [sfq].[fore_quart_loc] = 'w'
ORDER BY
[sfq].[fore_quart_month]
The issue is that when including the NOT LIKE filters and the [sfq].[fore_quart_month] reference in the subquery, it runs incredibly slow (minutes), but if I remove the NOT LIKE filters or if I hard set the value instead of use the [sfq].[fore_quart_month] (which obviously means every calculation will use the wrong month except the one I hard coded), then the query runs in less than a second.
Any suggestions?
The LIKE queries with wild cards on both ends are very slow. Example: %MAC%
If you really need to search on that, consider creating a persisted computed boolean field and searching on that. Something like:
ALTER TABLE SO_Type
ADD IsMac AS CASE WHEN [Description] LIKE '%MAC%' THEN 1 ELSE 0 END PERSISTED
GO
OR
As an alternative, set ISMac whenever data is inserted
Small tip: you can group by month and join subquery to main datasource in from clause. This will let (which is not must) server perform subquery only once. And please note my comment above.
...
FROM [authmanager2].[dbo].[sales_forecast_quarterly][sfq]
INNER JOIN
(
SELECT SUM([FORE].[Revenue]) as [Revenue], MONTH([soa].[last_updated_utc]) as [Month]
FROM [SO_Opportunity][SO]
INNER JOIN [SO_Type] ON [SO].[SO_Type_RecID] = [SO_Type].[SO_Type_RecID]
...
GROUP BY MONTH([soa].[last_updated_utc])
) rev on rev.[Month] = [sfq].[fore_quart_month]

Access data source using SQL to show most recent entry per site

First of all I am a complete beginner to SQL and have been thrown in at the deep end a bit ! I'm learning as I go along and each mistake I make or question I ask will hopefully help me develop... please be kind :)
I have a working query that extracts electricty meter readings and other information. I am after finding the most recent reading for each site. This is the query at the moment :
PARAMETERS [Site Group] Text ( 255 );
SELECT
Lookup.Lookup_Name AS [Group],
Contacts.Name AS Site,
Points.Number AS MPAN,
Max(DataElectricity.Date) AS MaxDate,
DataElectricity.M1_Present,
DataElectricity.M2_Present,
DataElectricity.M3_Present,
DataElectricity.M4_Present,
DataElectricity.M5_Present,
DataElectricity.M6_Present,
DataElectricity.M7_Present,
DataElectricity.M8_Present,
DataElectricity.Direct
FROM
DataElectricity INNER JOIN (Lookup INNER JOIN (Points INNER JOIN Contacts ON Points.Contacts_Id = Contacts.Id) ON Lookup.Lookup_Id = Contacts.Group_1) ON DataElectricity.Point_Id = Points.Id
WHERE
((DataElectricity.Direct)='D')
GROUP BY
Lookup.Lookup_Name, Contacts.Name, Points.Number, DataElectricity.M1_Present, DataElectricity.M2_Present, DataElectricity.M3_Present, DataElectricity.M4_Present, DataElectricity.M5_Present, DataElectricity.M6_Present, DataElectricity.M7_Present, DataElectricity.M8_Present, DataElectricity.Direct
ORDER BY
Lookup.Lookup_Name, Contacts.Name, Max(DataElectricity.Date) DESC;
However this returns all the readings for a site rather than just the most recent... I'm sure this is simple but I can't figure it out.
Any advice or guidence is gratefully received :)
Can't you just use top 1 to get only the first result?
SELECT top 1 ...
I have evolved the code a bit further using caspian's suggestion of SELECT top 1... but am struggling to refine it further and produce the result I need.
PARAMETERS [Site Group] Text ( 255 );
SELECT
Lookup.Lookup_Name,
Contacts.Name AS Site,
Points.Number AS MPAN,
DataElectricity.M1_Present,
DataElectricity.M2_Present,
DataElectricity.M3_Present,
DataElectricity.M4_Present,
DataElectricity.M5_Present,
DataElectricity.M6_Present,
DataElectricity.M7_Present,
DataElectricity.M8_Present,
DataElectricity.Direct
FROM
(
SELECT TOP 1 DataElectricity.Date AS MaxDate,
DataElectricity.M1_Present,
DataElectricity.M2_Present,
DataElectricity.M3_Present,
DataElectricity.M4_Present,
DataElectricity.M5_Present,
DataElectricity.M6_Present,
DataElectricity.M7_Present,
DataElectricity.M8_Present,
DataElectricity.Point_id
FROM
DataElectricity
ORDER BY MaxDate DESC
)
DataElectricity INNER JOIN (Lookup INNER JOIN (Points INNER JOIN Contacts ON Points.Contacts_Id = Contacts.Id) ON Lookup.Lookup_Id = Contacts.Group_1) ON DataElectricity.Point_Id = Points.Id
WHERE
((Lookup.Lookup_Name)=Lookup_Name)
ORDER BY
Lookup.Lookup_Name, Contacts.Name, MaxDate DESC;
I do have a Google Drive file showing a small example of the data tables and desired result with hopfully a clear guide as to how the tables connect.
https://docs.google.com/file/d/0BybrcUCD29TxWVRsV1VtTm1Bems/edit?usp=sharing
The actual data contains hundreds of Site Groups each with potentially hundreds of sites.
I would like my end users to be able to select the Site Group name from the Lookup.Lookup_Name list and for it to return all the relevant sites and readings.
.... I really hope that makes sense !