Trigger to insert new quote number in this format - database-trigger

I am very new at triggers - actually this will be my first one.
What I am trying to achieve is the following:
When I create a new Sales Opportunity, the Quote no field needs to spit out a number starting from this Q1500/09/2017 so Q is the prefix, 1500 is the first quote number, 09 the month and 2017 the year.
Can someone assist me in getting this right - do i need a SP and a table in order for my trigger to work correctly?
Quote_No is a table field so I'm guessing it should look something like this:
CREATE TABLE [dbo].[Quote_Pref_No](
[Yr] [varchar](4) NULL,
[Mth] [varchar](2) NULL,
[Quote_Pref] [varchar](10) NULL,
[Quote_No] [int] NULL
) ON [PRIMARY]
Then the SP:
Create Proc [dbo].[New_Quote_Num] #ClientID varchar(24),#ContactNum int, #Year varchar(4), #mth varchar(2)
As
Begin
Declare #Pref varchar(5),
#Num int,
#QuoteNo varchar(255)
Select #QuoteNo = B.Description
From dbo.AMGR_User_Fields_Tbl A inner join dbo.AMGR_User_Field_Defs_Tbl B
on A.Type_Id = B.Type_Id and A.Code_Id = B.Code_Id and A.Type_Id = 117
Where A.Client_Id = #ClientId and A.Contact_Number = #ContactNum
Select #Pref = Quote_Pref, #Num = Quote_No + 1
From dbo.Quote_Pref_No
Where Yr = #Year and Mth = #Mth
Set #QuoteNum = 'Q/'+Right(#Year,2)+'/'+Right(#mth,2)+'/'+#Pref+case when Len(#Num) <= 3 then Right('000000'+Convert(Varchar(55),#Num),3) else CONVERT(Varchar(55),#Num) end
Insert into dbo.O_QuoteNo(Client_Id,Contact_Number,Type_Id,Code_Id,O_QuoteNo)
Values(#ClientId,#ContactNum,13,0,#QuoteNum)
Update dbo.Quote_Pref_No
Set Quote_No = #Num
Where Yr = #Year and mth = #mth
End
Grant execute on dbo.New_Quote_Num to CRMGroup
GO
I just dont know how to generate the month and year together.
Trigger code:
Create Trigger [dbo].[QuoteNew]
on [dbo].[AMGR_User_Fields_Tbl] after insert
As
Declare #ClientId varchar(24),
#ContactNum int,
#TypeId int,
#Year varchar(4),
#quoteYear varchar(4),
#mth varchar(2)
Select #ClientId = Client_Id,
#ContactNum = Contact_Number,
#TypeId = TYPE_ID,
#Year = CONVERT(varchar(4),Datepart(yyyy,DateCol)) from inserted
#mth = convert(varchar(2), datepart(mm,Datecol)) from inserted
Select #quoteYear = Yr from dbo.quote_Pref_No where Yr = #Year
select #mth = mth from dbo.quote_Pref_No where mth = #mth
If #TypeID = 117 and #QuoteYear is null or #quoteYear = ''
Begin
Execute dbo.New_Year_Certs #Year
Execute dbo.New_quote_Num #ClientId,#ContactNum,#Year
End
If #TypeID = 117 and #quoteYear = #Year
Begin
Execute dbo.New_Cert_Num #ClientId,#ContactNum,#Year
End
GO
Do I need to create a separate SP for month or can I do both month and year in one SP?

Related

Power Query conditional sumif

I need to add a column that Sums the value column of all columns that have a common id. However, any id = null is not summed, but equal to the value column.
The above example should result in:
TopPaymendId JournalLineNetAmount TopAmount
fcbcd407-ca26-4ea0-839a-c39767d05403 -3623.98 -7061.23
fcbcd407-ca26-4ea0-839a-c39767d05403 -3437.25 -7061.23
ce77faac-1638-40e9-ad62-be1813ce9031 -88.68 -88.68
531d9bde-3f52-47f3-a9cf-6f3566733af2 -152.23 -152.23
8266dfef-dd14-4654-a6d2-091729defde7 229.42 229.42
f8b97a47-15ef-427d-95e0-ce23cc8efb1f -777 -777
null -3.01 -3.01
null -2.94 -2.94
null 3312.5 3312.5
This code should work:
let
Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
group = Table.Group(Source, {"TopPaymendId"}, {"TopAmount", each List.Sum([JournalLineNetAmount])}),
join = Table.Join(Source,{"TopPaymendId"},group,{"TopPaymendId"}),
replace = Table.ReplaceValue(join,each [TopAmount],each if [TopPaymendId] = null
then [JournalLineNetAmount] else [TopAmount],Replacer.ReplaceValue,{"TopAmount"})
in
replace

Get inserted uniqueidentifier from table B when its inserted from Table A insert trigger

I wasnt sure how to open the title but let me explain what is my problem.
I have two tables and both of them used uniqueidentifier as Id and they are auto generated by newsequentialid()
Now, when i make an insert to table B, it runes Insert trigger and i do some specific things inside this trigger and i also insert some values to another table called A and i need to retreive this table A's inserted Id but i am unable to find a solution.
Also let me explain why i need such a trigger. When a user creates an invoice with products in it where they have stock information, this trigger is responsible to create a stock transaction with header and detail about the products inserted (this stock detail table also has a trigger and it updates the warehouses) etc. etc.
i hope this gives some hint what i am trying to do
CREATE TRIGGER [dbo].[IT_TBLDebitInvoiceDetails] ON [dbo].[TBLDebitInvoiceDetails] AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
declare #cnt int;
--HEADER
declare #DocumentId uniqueidentifier;
declare #OrganizationId uniqueidentifier;
declare #Date date;
declare #TermDate date;
declare #DespatchDate date;
declare #DespatchNo nvarchar(20);
declare #WarehouseId uniqueidentifier;
declare #CustomerId uniqueidentifier;
declare #StockId uniqueidentifier;
declare #CurrencyTypeId uniqueidentifier;
declare #GrandTotal money;
--Auditable
declare #WhoCreated uniqueidentifier;
declare #DateCreated datetime;
declare #WhoUpdated uniqueidentifier;
declare #DateUpdated datetime;
--DETAIL
declare #ProductId uniqueidentifier;
declare #Quantity decimal(18, 2);
declare #ProductType int;
SELECT TOP(1) #OrganizationId = OrganizationId, #DocumentId = A.Id, #Date = A.[Date], #TermDate = A.TermDate, #DespatchDate = A.DespatchDate, #DespatchNo = A.DespatchNo,
#WarehouseId = A.WarehouseId, #CustomerId = A.CustomerId, #GrandTotal = A.GrandTotal,
#WhoCreated = A.WhoCreated, #DateCreated = A.DateCreated, #WhoUpdated = A.WhoUpdated, #DateUpdated = A.DateUpdated
FROM TBLDebitInvoices AS A
INNER JOIN inserted AS B ON A.Id = B.InvoiceId
/* CHECK STOCK TRANSACTION */
SELECT #cnt = COUNT(*) FROM inserted AS A
INNER JOIN TBLProducts AS B ON B.Id = A.ProductId
WHERE B.ProductType != 1
--we have products for stock, create stock header
IF(#cnt > 0)
BEGIN
INSERT INTO TBLStocks (OrganizationId, TransactionType, DocumentType, DocumentId, [Date], DeliveryDate, DeliveryNo, SourceWarehouseId, CustomerId, [Description], WhoCreated, DateCreated, WhoUpdated, DateUpdated, IsDeleted)
VALUES (#OrganizationId, 5, 0, #DocumentId, #Date, #DespatchDate, #DespatchNo, #WarehouseId, #CustomerId, '', #WhoCreated, #DateCreated, #WhoUpdated, #DateUpdated, 0);
SELECT #StockId = ???????;
END
INSERT INTO TBLStockDetails (StockId, ProductId, [Value])
SELECT #StockId, ProductId, SUM(Quantity) FROM (
SELECT A.ProductId AS ProductId, A.Quantity FROM inserted AS A
INNER JOIN TBLProducts AS B ON B.Id = A.ProductId
WHERE B.ProductType = 0
UNION ALL
SELECT C.IngredientID, A.Quantity * C.Quantity FROM inserted AS A
INNER JOIN TBLProducts AS B ON B.Id = A.ProductId
INNER JOIN TBLProductRecipes AS C ON C.ProductId = B.Id
WHERE B.ProductType = 2
) AS T1
GROUP BY ProductId;
UPDATE TBLDebitInvoices SET StockId = #StockId WHERE Id = #DocumentId;
/* CHECK DC TRANSACTION */
INSERT INTO TBLDebitCreditTransactions (TransactionType, DocumentType, DocumentId, PaymentStatus, [Date], Amount, AccountType, AccountId, CurrencyTypeId)
VALUES (1, 0, #DocumentId, 0, #TermDate, #GrandTotal, 0, #CustomerId, #CurrencyTypeId);
END
GO
inside this trigger i have this insert:
INSERT INTO TBLStocks (OrganizationId, TransactionType, DocumentType, DocumentId, [Date], DeliveryDate, DeliveryNo, SourceWarehouseId, CustomerId, [Description], WhoCreated, DateCreated, WhoUpdated, DateUpdated, IsDeleted)
VALUES (#OrganizationId, 5, 0, #DocumentId, #Date, #DespatchDate, #DespatchNo, #WarehouseId, #CustomerId, '', #WhoCreated, #DateCreated, #WhoUpdated, #DateUpdated, 0);
SELECT #StockId = ???????;
and i need the Id inserted to this table so i can use its id to insert its row elements.
it seems i found the answer, i wasnt sure inserted statement will give a separate result for the second insert, but it works
DECLARE #IdTable TABLE (StockId uniqueidentifier);
INSERT INTO TBLStocks (OrganizationId, TransactionType, DocumentType, DocumentId, [Date], DeliveryDate, DeliveryNo, SourceWarehouseId, CustomerId, [Description], WhoCreated, DateCreated, WhoUpdated, DateUpdated, IsDeleted)
OUTPUT Inserted.Id INTO #IdTable(StockId)
SELECT #OrganizationId, 5, 0, #DocumentId, #Date, #DespatchDate, #DespatchNo, #WarehouseId, #CustomerId, '', #WhoCreated, #DateCreated, #WhoUpdated, #DateUpdated, 0;
SELECT #StockId = StockId FROM #IdTable;
this will give the second table inserted uniqueidentifier

Select nth to nth row while table still have values unselected with python and pyodbc

I have a table with 10,000 rows and I want to select the first 1000 rows and then select again and this time, the next set of rows, which is 1001-2001.
I am using the BETWEEN clause in order to select the range of values. I can also increment the values. Here is my code:
count = cursor.execute("select count(*) from casa4").fetchone()[0]
ctr = 1
ctr1 = 1000
str1 = ''
while ctr1 <= count:
sql = "SELECT AccountNo FROM ( \
SELECT AccountNo, ROW_NUMBER() OVER (ORDER BY Accountno) rownum \
FROM casa4 ) seq \
WHERE seq.rownum BETWEEN " + str(ctr) + " AND " + str(ctr1) + ""
ctr = ctr1 + 1
ctr1 = ctr1 + 1000
cursor.execute(sql)
sleep(2) #interval in printing of the rows.
for row in cursor:
str1 = str1 + '|'.join(map(str,row)) + '\n'
print "Records:" + str1 #var in storing the fetched rows from database.
print sql #prints the sql statement(str) and I can see that the var, ctr and ctr1 have incremented correctly. The way I want it.
What I want to achieve is using a messaging queue, RabbitMQ, I will send this rows to another database and I want to speed up the process. Selecting all and sending it to the queue returns an error.
The output of the code is that it returns 1-1000 rows correctly on the 1st but, on the 2nd loop, instead of 1001-2001 rows, it returns 1-2001 rows, 1-3001 and so on.. It always starts on 1.
I was able to recreate your issue with both pyodbc and pypyodbc. I also tried using
WITH seq (AccountNo, rownum) AS
(
SELECT AccountNo, ROW_NUMBER() OVER (ORDER BY Accountno) rownum
FROM casa4
)
SELECT AccountNo FROM seq
WHERE rownum BETWEEN 11 AND 20
When I run that in SSMS I just get rows 11 through 20, but when I run it from Python I get all the rows (starting from 1).
The following code does work using pyodbc. It uses a temporary table named #numbered, and might be helpful in your situation since your process looks like it would do all of its work using the same database connection:
import pyodbc
cnxn = pyodbc.connect("DSN=myDb_SQLEXPRESS")
crsr = cnxn.cursor()
sql = """\
CREATE TABLE #numbered (rownum INT PRIMARY KEY, AccountNo VARCHAR(10))
"""
crsr.execute(sql)
cnxn.commit()
sql = """\
INSERT INTO #numbered (rownum, AccountNo)
SELECT
ROW_NUMBER() OVER (ORDER BY Accountno) AS rownum,
AccountNo
FROM casa4
"""
crsr.execute(sql)
cnxn.commit()
sql = "SELECT AccountNo FROM #numbered WHERE rownum BETWEEN ? AND ? ORDER BY rownum"
batchsize = 1000
ctr = 1
while True:
crsr.execute(sql, [ctr, ctr + batchsize - 1])
rows = crsr.fetchall()
if len(rows) == 0:
break
print("-----")
for row in rows:
print(row)
ctr += batchsize
cnxn.close()

Select the record of a given id with the highest timestamp using DAO

How do I do the following using DAO on a recordset
SELECT TOP 1 * FROM foo WHERE id = 10 ORDER BY timestamp DESC
Using SetCurrentIndex you can only use one index it seems otherwise using id and timestamp and selecting the first one would work.
I am by no means sure of what you want.
Dim rs As DAO.Recordset
Dim db As Database
Set db = CurrentDB
sSQL = "SELECT TOP 1 * FROM foo WHERE id = 10 ORDER BY timestamp DESC"
Set rs = db.OpenRecordset(sSQL)
Find does not work with all recordsets. This will work:
Set rs = CurrentDb.OpenRecordset("select * from table1")
rs.FindFirst "akey=1 and atext='b'"
If Not rs.EOF Then Debug.Print rs!AKey
This will not:
Set rs = CurrentDb.OpenRecordset("table1")
rs.FindFirst "akey=1 and atext='b'"

Postgres Recursive query + group by + join in Django

My Requirement is to write a sql query to get the sub-region wise (fault)events count that occurred for the managedobjects. My database is postgres 8.4. Let me explain using the table structure.
My tables in django:
Managedobject:
class Managedobject(models.Model):
name = models.CharField(max_length=200, unique=True)
iscontainer = models.BooleanField(default=False,)
parentkey = models.ForeignKey('self', null=True)
Event Table:
class Event(models.Model):
Name = models.CharField(verbose_name=_('Name'))
foid = models.ForeignKey(Managedobject)
Managedobject Records:
NOC
Chennai
MO_1
MO_2
MO_3
Mumbai
MO_4
MO_5
MO_6
Delhi
Bangalore
IP
Calcutta
Cochin
Events Records:
event1 MO_1
event2 MO_2
event3 MO_3
event4 MO_5
event5 MO_6
Now I need to get the events count for all the sub-regions. For example,
for NOC region:
Chennai - 3
Mumbai - 2
Delhi - 0
Bangalore - 0
So far I am able to get the result in two different queries.
Get the subregions.
select id from managedobject where iscontainer = True and parentkey = 3489
For each of the region (using for loop), get the count as follows:
SELECT count(*)
from event ev
WHERE ev.foid
IN (
WITH RECURSIVE q AS (
SELECT h
FROM managedobject h
WHERE parentkey = 3489
UNION ALL
SELECT hi
FROM q
JOIN managedobject hi
ON hi.parentkey = (q.h).id
)
SELECT (q.h).id FROM q
)
Please help to combine the queries to make it a single query and for getting the top 5 regions. Since the query is difficult in django, I am going for a raw sql query.
I got the query:
WITH RECURSIVE q AS (
SELECT h,
1 AS level,
id AS ckey,
displayname as dname
FROM managedobject h
WHERE parentkey = 3489
and logicalnode=True
UNION ALL
SELECT hi,
q.level + 1 AS level,
ckey,
dname
FROM q
JOIN managedobject hi ON hi.parentkey = (q.h).id
)
SELECT count(ckey) as ccount,
ckey,
dname
FROM q
JOIN event as ev on ev.foid_id = (q.h).id
GROUP BY ckey, dname
ORDER BY ccount DESC
LIMIT 5