我想实施某种"数据库"在Prolog。
我有两个想法来建模表和行:
% First one
client('B069','Laurent','769, rue de la LALALA','LLN','A1',10000).
% Second one
data(client,'B069',name,'Laurent').
data(client,'B069',adress,'69, rue de la LALALA').
data(client,'B069',town,'LLN').
data(client,'B069',cat,'A1').
data(client,'B069',amount,10000).
使用这两个模型,我可以分别制作一个" SELECT ID FROM client WHERE amount> 0"对于积极金额的客户:
% First one
client1_positive(Client) :- findall(ID,(data(client,ID,compte,Amount),Amount>0),Client).
% Second one
client2_positive(Client) :- findall(ID,(client(ID,_,_,_,_,Amount),Amount>0),Client).
它们都具有相同的输出;
?- client1_positive(Clients).
Client = ['B069'].
?- client2_positive(Clients).
Client = ['B069'].
但这是我的问题,因为我对Prolog很新,我完全不知道如何让它变得如此动态,例如" SELECT name FROM client WHERE ID =' B069&#39 ; &#34 ;.我可以为这个特定的SQL查询实现一个规则,但是我找不到实现更抽象规则的方法,因此可以解释每个查询。
对于如何在Prolog中建模这些数据,是否有最好的实践?关于如何在Prolog中提出更抽象的请求的一些想法(不是对我的问题的详细解答)?
非常感谢
答案 0 :(得分:2)
考虑如何使用关系数据库执行此操作。您可能有一个Client表,其中包含客户端ID(密钥),客户端名称,地址,电话和其他联系信息的记录。你不会想要一个单独的姓名,地址,电话等记录。这太麻烦了。
对于与客户端有一定关系的客户端数据,您将拥有单独的表(一对一,多对一,多对多,......)。如果客户端可能有多组联系人信息,那么这是联系人信息和客户端之间的多对一关系,因此您需要设置一个单独的ContactInfo表,其中“contact_info_id”作为主键,并且会有内容contact_info_id,客户ID,联系信息的记录。对于您的示例中的金额,您将拥有一个Amount表,其记录包含金额ID(密钥),客户ID,金额。
要在Prolog中执行此操作,您的结构基本相同。设置client
数据和amount
数据:
% clients
client('B069', 'John Doe', '123 Main St', 123-456-1234).
client('B070', 'Jane Smith', '100 West Elm', 999-999-8888).
...
% amounts
amount('A010', 'B069', 10000).
amount('A010', 'B070', 10100).
...
以上可以是一对一或多对一。
相当于查询:SELECT name FROM client WHERE ID = 'B069'
将是:
?- client('B069', Name, Address, Phone).
您选择的正数将是:
client_positive(Clients) :-
findall(ClientId, (amount(_, ClientId, Amount), Amount > 0), Clients).
答案 1 :(得分:0)
你的第一种方法很好。例如,你可能需要第二个,例如a 一个人可以拥有多个地址。
查询只是一个带变量的术语:
Option Explicit
Sub Main()
Dim cell As Range, newRowRng As Range, myRow As Range, f As Range
Dim firstAddress As String
With Sheets("myDataSheetName") '<--| change "myDataSheetName" to your actual sheet name
With .Range("A1", .cells(.Rows.Count, "S").End(xlUp)) '<--| reference its columns A:S range from row 1 (header) down to the one corresponding to last column S not empty row
FormatDefault .cells '<--| set all range cells to their "default" format
.AutoFilter Field:=19, Criteria1:="New row" '<--| filter column S cells with "New row"
If Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) > 1 Then Set newRowRng = .Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible) '<--| if any filtered cells other than headers then set 'newRowRng' to them
.Parent.AutoFilterMode = False '<--| remove autofilter
End With
If newRowRng Is Nothing Then Exit Sub '<--| if no "newRow" in column S then exit sub
For Each myRow In Intersect(newRowRng, .Columns(1)) '<--| loop through column A "filtered" cells
If myRow.Value = myRow.Offset(-1).Value Then '<--| if current cell value equals the one above
With Intersect(newRowRng, myRow.EntireRow) '<--| reference current cell entire data row
Set f = .Find(what:="y", LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False) '<--| search it for "y"
If Not f Is Nothing Then '<--| if found
firstAddress = f.Address '<--| store first found cell address
Do '<--| start a loop
If Len(f.Offset(-1)) = 0 Then FormatCell f '<--| if empty cell above current found cell thne set this latter format
Set f = .FindNext(f) '<--| search for the next "y"
Loop While Not f.Address = firstAddress '<--| exit whne 'Find()' wraps back to first found cell
End If
End With
End If
Next
End With
End Sub
Sub FormatDefault(rng As Range)
With rng
With .Font
.Color = 0
.TintAndShade = 0
End With
With .Interior
.Color = 16777215
.PatternColorIndex = -4142
.TintAndShade = 0
End With
End With
End Sub
Sub FormatCell(rng As Range)
With rng
With .Font
.Color = -16383844
.TintAndShade = 0
End With
With .Interior
.PatternColorIndex = xlAutomatic
.Color = 13551615
.TintAndShade = 0
End With
End With
End Sub
您可以使用任何参数作为查询中的键。您的Prolog可能不会对所有这些内容编制索引,这可能是也可能不是问题。
| ?- client('B069',Name,Adress,Town,Cat,Amount).
Cat = 'A1',
Name = 'Laurent',
Town = 'LLN',
Adress = '769, rue de la LALALA',
Amount = 10000 ?
如果有多个答案,则会通过回溯返回。 Findall将它们收集在一个列表中,这可能是您想要的,也可能不是。
如果通过&#34;动态&#34;您的意思是在数据库中添加和删除内容,然后您可以| ?- client(Key,'Laurent',_,_,_,_).
Key = 'B069' ?
和assert/1
。